summaryrefslogtreecommitdiffstats
path: root/chrome/browser/download/download_shelf.cc
diff options
context:
space:
mode:
authortfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-06 22:23:59 +0000
committertfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-06 22:23:59 +0000
commit3a8fb455a8568a55178370917ddb575887b5bc53 (patch)
tree2c69e433e38f088090108452af584027862ca4fa /chrome/browser/download/download_shelf.cc
parent20ed20a91fb4ac42aad27fac482ffcff6f9f6fc3 (diff)
downloadchromium_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.cc234
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) {