diff options
author | tfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-06 22:23:59 +0000 |
---|---|---|
committer | tfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-06 22:23:59 +0000 |
commit | 3a8fb455a8568a55178370917ddb575887b5bc53 (patch) | |
tree | 2c69e433e38f088090108452af584027862ca4fa /chrome/browser/download/download_shelf.cc | |
parent | 20ed20a91fb4ac42aad27fac482ffcff6f9f6fc3 (diff) | |
download | chromium_src-3a8fb455a8568a55178370917ddb575887b5bc53.zip chromium_src-3a8fb455a8568a55178370917ddb575887b5bc53.tar.gz chromium_src-3a8fb455a8568a55178370917ddb575887b5bc53.tar.bz2 |
Reland "download: Move constants from download_util.h to DownloadShelf."
The first patch was reverted because it introduced static initializers.
# a (anonymous namespace)::kDownloadItemHeight
# a __init_array_end+0x5030
# a (anonymous namespace)::kBodyWidth
# a (anonymous namespace)::kBodyHeight
# a (anonymous namespace)::kMinDownloadItemWidth
# a __init_array_end+0x5030
This was the command line: python
./tools/linux/dump-static-initializers.py -d out/Release/chrome
To avoid the static initializers we initialize the values of the constants directly in the header file.
The original patch: https://codereview.chromium.org/19529004 - crrev.com/213775
The reverted patch: https://codereview.chromium.org/20678002 - crrev.com/213780
Changed to use enum technique. According to Ami Fischman it has the following benefits:
- guaranteeing compiler replacement with literals; no need to guess at the whether math will lead to SI
- no need for boilerplate line per constant in the .cc file
- guarantee that nobody will get clever and play const_cast games with your constants.
BUG=104549
TBR=benjhayden@chromium.org
Review URL: https://codereview.chromium.org/21663003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@216000 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/download/download_shelf.cc')
-rw-r--r-- | chrome/browser/download/download_shelf.cc | 234 |
1 files changed, 233 insertions, 1 deletions
diff --git a/chrome/browser/download/download_shelf.cc b/chrome/browser/download/download_shelf.cc index f262e0a..ac18136 100644 --- a/chrome/browser/download/download_shelf.cc +++ b/chrome/browser/download/download_shelf.cc @@ -2,11 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#define _USE_MATH_DEFINES // For VC++ to get M_PI. This has to be first. + #include "chrome/browser/download/download_shelf.h" +#include <cmath> + #include "base/bind.h" #include "base/callback.h" #include "base/message_loop/message_loop.h" +#include "base/strings/string_number_conversions.h" #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_service.h" #include "chrome/browser/download/download_service_factory.h" @@ -20,7 +25,17 @@ #include "content/public/browser/download_manager.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_view.h" +#include "grit/locale_settings.h" +#include "grit/theme_resources.h" #include "ui/base/animation/animation.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/image/image_skia.h" + +#if defined(TOOLKIT_VIEWS) +#include "ui/views/view.h" +#endif using content::DownloadItem; @@ -29,6 +44,19 @@ namespace { // Delay before we show a transient download. const int64 kDownloadShowDelayInSeconds = 2; +// Get the opacity based on |animation_progress|, with values in [0.0, 1.0]. +// Range of return value is [0, 255]. +int GetOpacity(double animation_progress) { + DCHECK(animation_progress >= 0 && animation_progress <= 1); + + // How many times to cycle the complete animation. This should be an odd + // number so that the animation ends faded out. + static const int kCompleteAnimationCycles = 5; + double temp = animation_progress * kCompleteAnimationCycles * M_PI + M_PI_2; + temp = sin(temp) / 2 + 0.5; + return static_cast<int>(255.0 * temp); +} + } // namespace DownloadShelf::DownloadShelf() @@ -37,7 +65,211 @@ DownloadShelf::DownloadShelf() weak_ptr_factory_(this) { } -DownloadShelf::~DownloadShelf() { +DownloadShelf::~DownloadShelf() {} + +// static +int DownloadShelf::GetBigProgressIconSize() { + static int big_progress_icon_size = 0; + if (big_progress_icon_size == 0) { + base::string16 locale_size_str = + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BIG_PROGRESS_SIZE); + bool rc = base::StringToInt(locale_size_str, &big_progress_icon_size); + if (!rc || big_progress_icon_size < kBigProgressIconSize) { + NOTREACHED(); + big_progress_icon_size = kBigProgressIconSize; + } + } + + return big_progress_icon_size; +} + +// static +int DownloadShelf::GetBigProgressIconOffset() { + return (GetBigProgressIconSize() - kBigIconSize) / 2; +} + +// Download progress painting -------------------------------------------------- + +// Common images used for download progress animations. We load them once the +// first time we do a progress paint, then reuse them as they are always the +// same. +gfx::ImageSkia* g_foreground_16 = NULL; +gfx::ImageSkia* g_background_16 = NULL; +gfx::ImageSkia* g_foreground_32 = NULL; +gfx::ImageSkia* g_background_32 = NULL; + +// static +void DownloadShelf::PaintCustomDownloadProgress( + gfx::Canvas* canvas, + const gfx::ImageSkia& background_image, + const gfx::ImageSkia& foreground_image, + int image_size, + const gfx::Rect& bounds, + int start_angle, + int percent_done) { + // Draw the background progress image. + canvas->DrawImageInt(background_image, + bounds.x(), + bounds.y()); + + // Layer the foreground progress image in an arc proportional to the download + // progress. The arc grows clockwise, starting in the midnight position, as + // the download progresses. However, if the download does not have known total + // size (the server didn't give us one), then we just spin an arc around until + // we're done. + float sweep_angle = 0.0; + float start_pos = static_cast<float>(kStartAngleDegrees); + if (percent_done < 0) { + sweep_angle = kUnknownAngleDegrees; + start_pos = static_cast<float>(start_angle); + } else if (percent_done > 0) { + sweep_angle = static_cast<float>(kMaxDegrees / 100.0 * percent_done); + } + + // Set up an arc clipping region for the foreground image. Don't bother using + // a clipping region if it would round to 360 (really 0) degrees, since that + // would eliminate the foreground completely and be quite confusing (it would + // look like 0% complete when it should be almost 100%). + canvas->Save(); + if (sweep_angle < static_cast<float>(kMaxDegrees - 1)) { + SkRect oval; + oval.set(SkIntToScalar(bounds.x()), + SkIntToScalar(bounds.y()), + SkIntToScalar(bounds.x() + image_size), + SkIntToScalar(bounds.y() + image_size)); + SkPath path; + path.arcTo(oval, + SkFloatToScalar(start_pos), + SkFloatToScalar(sweep_angle), false); + path.lineTo(SkIntToScalar(bounds.x() + image_size / 2), + SkIntToScalar(bounds.y() + image_size / 2)); + + // gfx::Canvas::ClipPath does not provide for anti-aliasing. + canvas->sk_canvas()->clipPath(path, SkRegion::kIntersect_Op, true); + } + + canvas->DrawImageInt(foreground_image, + bounds.x(), + bounds.y()); + canvas->Restore(); +} + +// static +void DownloadShelf::PaintDownloadProgress(gfx::Canvas* canvas, +#if defined(TOOLKIT_VIEWS) + views::View* containing_view, +#endif + int origin_x, + int origin_y, + int start_angle, + int percent_done, + PaintDownloadProgressSize size) { + // Load up our common images. + if (!g_background_16) { + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); + g_foreground_16 = rb.GetImageSkiaNamed(IDR_DOWNLOAD_PROGRESS_FOREGROUND_16); + g_background_16 = rb.GetImageSkiaNamed(IDR_DOWNLOAD_PROGRESS_BACKGROUND_16); + g_foreground_32 = rb.GetImageSkiaNamed(IDR_DOWNLOAD_PROGRESS_FOREGROUND_32); + g_background_32 = rb.GetImageSkiaNamed(IDR_DOWNLOAD_PROGRESS_BACKGROUND_32); + DCHECK_EQ(g_foreground_16->width(), g_background_16->width()); + DCHECK_EQ(g_foreground_16->height(), g_background_16->height()); + DCHECK_EQ(g_foreground_32->width(), g_background_32->width()); + DCHECK_EQ(g_foreground_32->height(), g_background_32->height()); + } + + gfx::ImageSkia* background = + (size == BIG) ? g_background_32 : g_background_16; + gfx::ImageSkia* foreground = + (size == BIG) ? g_foreground_32 : g_foreground_16; + + const int kProgressIconSize = + (size == BIG) ? kBigProgressIconSize : kSmallProgressIconSize; + + // We start by storing the bounds of the images so that it is easy to mirror + // the bounds if the UI layout is RTL. + gfx::Rect bounds(origin_x, origin_y, + background->width(), background->height()); + +#if defined(TOOLKIT_VIEWS) + // Mirror the positions if necessary. + int mirrored_x = containing_view->GetMirroredXForRect(bounds); + bounds.set_x(mirrored_x); +#endif + + // Draw the background progress image. + canvas->DrawImageInt(*background, + bounds.x(), + bounds.y()); + + PaintCustomDownloadProgress(canvas, + *background, + *foreground, + kProgressIconSize, + bounds, + start_angle, + percent_done); +} + +// static +void DownloadShelf::PaintDownloadComplete(gfx::Canvas* canvas, +#if defined(TOOLKIT_VIEWS) + views::View* containing_view, +#endif + int origin_x, + int origin_y, + double animation_progress, + PaintDownloadProgressSize size) { + // Load up our common images. + if (!g_foreground_16) { + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); + g_foreground_16 = rb.GetImageSkiaNamed(IDR_DOWNLOAD_PROGRESS_FOREGROUND_16); + g_foreground_32 = rb.GetImageSkiaNamed(IDR_DOWNLOAD_PROGRESS_FOREGROUND_32); + } + + gfx::ImageSkia* complete = (size == BIG) ? g_foreground_32 : g_foreground_16; + + gfx::Rect complete_bounds(origin_x, origin_y, + complete->width(), complete->height()); +#if defined(TOOLKIT_VIEWS) + // Mirror the positions if necessary. + complete_bounds.set_x(containing_view->GetMirroredXForRect(complete_bounds)); +#endif + + // Start at full opacity, then loop back and forth five times before ending + // at zero opacity. + canvas->DrawImageInt(*complete, complete_bounds.x(), complete_bounds.y(), + GetOpacity(animation_progress)); +} + +// static +void DownloadShelf::PaintDownloadInterrupted(gfx::Canvas* canvas, +#if defined(TOOLKIT_VIEWS) + views::View* containing_view, +#endif + int origin_x, + int origin_y, + double animation_progress, + PaintDownloadProgressSize size) { + // Load up our common images. + if (!g_foreground_16) { + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); + g_foreground_16 = rb.GetImageSkiaNamed(IDR_DOWNLOAD_PROGRESS_FOREGROUND_16); + g_foreground_32 = rb.GetImageSkiaNamed(IDR_DOWNLOAD_PROGRESS_FOREGROUND_32); + } + + gfx::ImageSkia* complete = (size == BIG) ? g_foreground_32 : g_foreground_16; + + gfx::Rect complete_bounds(origin_x, origin_y, + complete->width(), complete->height()); +#if defined(TOOLKIT_VIEWS) + // Mirror the positions if necessary. + complete_bounds.set_x(containing_view->GetMirroredXForRect(complete_bounds)); +#endif + + // Start at zero opacity, then loop back and forth five times before ending + // at full opacity. + canvas->DrawImageInt(*complete, complete_bounds.x(), complete_bounds.y(), + GetOpacity(1.0 - animation_progress)); } void DownloadShelf::AddDownload(DownloadItem* download) { |