summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views
diff options
context:
space:
mode:
authorpaulg@google.com <paulg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-09-13 02:48:59 +0000
committerpaulg@google.com <paulg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-09-13 02:48:59 +0000
commitcdaa86594dcdd5fc4ccac5dbf63a5e4dbfcdb8ea (patch)
treec9e3f5a89a3d9733ea75b97153ef2be4e8425aa3 /chrome/browser/views
parent431838df78d6e3cd06794a45cf0243be32149c7c (diff)
downloadchromium_src-cdaa86594dcdd5fc4ccac5dbf63a5e4dbfcdb8ea.zip
chromium_src-cdaa86594dcdd5fc4ccac5dbf63a5e4dbfcdb8ea.tar.gz
chromium_src-cdaa86594dcdd5fc4ccac5dbf63a5e4dbfcdb8ea.tar.bz2
Move the download code to new directories:
browser/download/ browser/views/ Review URL: http://codereview.chromium.org/2826 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2166 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/views')
-rw-r--r--chrome/browser/views/bookmark_bar_view.cc2
-rw-r--r--chrome/browser/views/download_item_view.cc2
-rw-r--r--chrome/browser/views/download_item_view.h2
-rw-r--r--chrome/browser/views/download_shelf_view.cc6
-rw-r--r--chrome/browser/views/download_tab_view.cc1181
-rw-r--r--chrome/browser/views/download_tab_view.h252
-rw-r--r--chrome/browser/views/options/advanced_contents_view.cc2
7 files changed, 1440 insertions, 7 deletions
diff --git a/chrome/browser/views/bookmark_bar_view.cc b/chrome/browser/views/bookmark_bar_view.cc
index 9c26e82..9de3d13 100644
--- a/chrome/browser/views/bookmark_bar_view.cc
+++ b/chrome/browser/views/bookmark_bar_view.cc
@@ -15,7 +15,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/drag_utils.h"
-#include "chrome/browser/download_util.h"
+#include "chrome/browser/download/download_util.h"
#include "chrome/browser/history/history_backend.h"
#include "chrome/browser/history/history_database.h"
#include "chrome/browser/history/history.h"
diff --git a/chrome/browser/views/download_item_view.cc b/chrome/browser/views/download_item_view.cc
index 914a782..8ed9408 100644
--- a/chrome/browser/views/download_item_view.cc
+++ b/chrome/browser/views/download_item_view.cc
@@ -8,7 +8,7 @@
#include "chrome/app/theme/theme_resources.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/download_util.h"
+#include "chrome/browser/download/download_util.h"
#include "chrome/browser/views/download_shelf_view.h"
#include "chrome/common/gfx/chrome_canvas.h"
#include "chrome/common/resource_bundle.h"
diff --git a/chrome/browser/views/download_item_view.h b/chrome/browser/views/download_item_view.h
index ab42fd5..69adcc4 100644
--- a/chrome/browser/views/download_item_view.h
+++ b/chrome/browser/views/download_item_view.h
@@ -23,7 +23,7 @@
#include "base/timer.h"
#include "chrome/common/slide_animation.h"
#include "chrome/browser/cancelable_request.h"
-#include "chrome/browser/download_manager.h"
+#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/icon_manager.h"
#include "chrome/views/event.h"
#include "chrome/views/view.h"
diff --git a/chrome/browser/views/download_shelf_view.cc b/chrome/browser/views/download_shelf_view.cc
index 2ea2f4b..df6b7d5 100644
--- a/chrome/browser/views/download_shelf_view.cc
+++ b/chrome/browser/views/download_shelf_view.cc
@@ -8,12 +8,12 @@
#include "chrome/app/theme/theme_resources.h"
#include "chrome/browser/browser.h"
-#include "chrome/browser/download_item_model.h"
-#include "chrome/browser/download_manager.h"
-#include "chrome/browser/download_tab_view.h"
+#include "chrome/browser/download/download_item_model.h"
+#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/navigation_entry.h"
#include "chrome/browser/tab_contents.h"
#include "chrome/browser/views/download_item_view.h"
+#include "chrome/browser/views/download_tab_view.h"
#include "chrome/common/gfx/chrome_canvas.h"
#include "chrome/common/l10n_util.h"
#include "base/logging.h"
diff --git a/chrome/browser/views/download_tab_view.cc b/chrome/browser/views/download_tab_view.cc
new file mode 100644
index 0000000..8c31275
--- /dev/null
+++ b/chrome/browser/views/download_tab_view.cc
@@ -0,0 +1,1181 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/views/download_tab_view.h"
+
+#include <time.h>
+
+#include <algorithm>
+#include <functional>
+
+#include "base/file_util.h"
+#include "base/string_util.h"
+#include "base/task.h"
+#include "base/time_format.h"
+#include "base/timer.h"
+#include "chrome/app/theme/theme_resources.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/user_metrics.h"
+#include "chrome/common/gfx/chrome_canvas.h"
+#include "chrome/common/gfx/chrome_font.h"
+#include "chrome/common/l10n_util.h"
+#include "chrome/common/resource_bundle.h"
+#include "chrome/common/stl_util-inl.h"
+#include "chrome/common/time_format.h"
+#include "chrome/views/background.h"
+#include "googleurl/src/gurl.h"
+#include "generated_resources.h"
+
+// Approximate spacing, in pixels, taken from initial UI mock up screens
+static const int kVerticalPadding = 5;
+static const int kHorizontalButtonPadding = 15;
+
+// For vertical and horizontal element spacing
+static const int kSpacer = 20;
+
+// Horizontal space between the left edge of the entries and the
+// left edge of the view.
+static const int kLeftMargin = 38;
+
+// x-position of the icon (massage this so it visually matches
+// kDestinationSearchOffset in native_ui_contents.cc
+static const int kDownloadIconOffset = 132;
+
+// Padding between the progress icon and the title, url
+static const int kInfoPadding = 16;
+
+// Horizontal distance from the left window edge to the left icon edge
+static const int kDateSize = 132;
+
+// Maximum size of the text for the file name or URL
+static const int kFilenameSize = 350;
+
+// Maximum size of the progress text during download, which is taken
+// out of kFilenameSize
+static const int kProgressSize = 170;
+
+// Status label color (grey)
+static const SkColor kStatusColor = SkColorSetRGB(128, 128, 128);
+
+// URL label color (green)
+static const SkColor kUrlColor = SkColorSetRGB(0, 128, 0);
+
+// Paused download indicator (red)
+static const SkColor kPauseColor = SkColorSetRGB(128, 0, 0);
+
+// Selected item background color
+static const SkColor kSelectedItemColor = SkColorSetRGB(215, 232, 255);
+
+// State key used to identify search text.
+static const wchar_t kSearchTextKey[] = L"st";
+
+// Sorting functor for DownloadItem --------------------------------------------
+
+// Sort DownloadItems into ascending order by their start time.
+class DownloadItemSorter : public std::binary_function<DownloadItem*,
+ DownloadItem*,
+ bool> {
+ public:
+ bool operator()(const DownloadItem* lhs, const DownloadItem* rhs) {
+ return lhs->start_time() < rhs->start_time();
+ }
+};
+
+
+// DownloadItemTabView implementation ------------------------------------------
+DownloadItemTabView::DownloadItemTabView()
+ : model_(NULL),
+ parent_(NULL) {
+ // Create our element views using empty strings for now,
+ // set them based on the model's state in Layout().
+ since_ = new ChromeViews::Label(L"");
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ ChromeFont font = rb.GetFont(ResourceBundle::WebFont);
+ since_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
+ since_->SetFont(font);
+ AddChildView(since_);
+
+ date_ = new ChromeViews::Label(L"");
+ date_->SetColor(kStatusColor);
+ date_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
+ date_->SetFont(font);
+ AddChildView(date_);
+
+ // file_name_ is enabled once the download has finished and we can open
+ // it via ShellExecute.
+ file_name_ = new ChromeViews::Link(L"");
+ file_name_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
+ file_name_->SetController(this);
+ file_name_->SetFont(font);
+ AddChildView(file_name_);
+
+ // Set our URL name
+ download_url_ = new ChromeViews::Label(L"");
+ download_url_->SetColor(kUrlColor);
+ download_url_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
+ download_url_->SetFont(font);
+ AddChildView(download_url_);
+
+ // Set our time remaining
+ time_remaining_ = new ChromeViews::Label(L"");
+ time_remaining_->SetColor(kStatusColor);
+ time_remaining_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
+ time_remaining_->SetFont(font);
+ AddChildView(time_remaining_);
+
+ // Set our download progress
+ download_progress_ = new ChromeViews::Label(L"");
+ download_progress_->SetColor(kStatusColor);
+ download_progress_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
+ download_progress_->SetFont(font);
+ AddChildView(download_progress_);
+
+ // Set our 'Pause', 'Cancel' and 'Show in folder' links using
+ // actual strings, since these are constant
+ pause_ = new ChromeViews::Link(l10n_util::GetString(IDS_DOWNLOAD_LINK_PAUSE));
+ pause_->SetController(this);
+ pause_->SetFont(font);
+ AddChildView(pause_);
+
+ cancel_ = new ChromeViews::Link(
+ l10n_util::GetString(IDS_DOWNLOAD_LINK_CANCEL));
+ cancel_->SetController(this);
+ cancel_->SetFont(font);
+ AddChildView(cancel_);
+
+ show_ = new ChromeViews::Link(l10n_util::GetString(IDS_DOWNLOAD_LINK_SHOW));
+ show_->SetController(this);
+ show_->SetFont(font);
+ AddChildView(show_);
+}
+
+DownloadItemTabView::~DownloadItemTabView() {
+}
+
+void DownloadItemTabView::SetModel(DownloadItem* model,
+ DownloadTabView* parent) {
+ DCHECK(model && parent);
+ model_ = model;
+ parent_ = parent;
+ parent_->LookupIcon(model_);
+}
+
+void DownloadItemTabView::GetPreferredSize(CSize* out) {
+ CSize pause_size;
+ pause_->GetPreferredSize(&pause_size);
+ CSize cancel_size;
+ cancel_->GetPreferredSize(&cancel_size);
+ CSize show_size;
+ show_->GetPreferredSize(&show_size);
+
+ out->cx = download_util::kBigProgressIconSize +
+ 2 * kSpacer +
+ kHorizontalButtonPadding +
+ kFilenameSize +
+ std::max(pause_size.cx + cancel_size.cx + kHorizontalButtonPadding,
+ show_size.cx);
+
+ out->cy = download_util::kBigProgressIconSize;
+}
+
+// Each DownloadItemTabView has reasonably complex layout requirements
+// that are based on the state of its model. To make the code much simpler
+// to read, Layout() is split into state specific code which will result
+// in some redundant code.
+void DownloadItemTabView::Layout() {
+ DCHECK(model_);
+ switch (model_->state()) {
+ case DownloadItem::COMPLETE:
+ LayoutComplete();
+ break;
+ case DownloadItem::CANCELLED:
+ LayoutCancelled();
+ break;
+ case DownloadItem::IN_PROGRESS:
+ LayoutInProgress();
+ break;
+ case DownloadItem::REMOVING:
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+// Only display the date if the download is the last that occurred
+// on a given day.
+void DownloadItemTabView::LayoutDate() {
+ if (!parent_->ShouldDrawDateForDownload(model_)) {
+ since_->SetVisible(false);
+ date_->SetVisible(false);
+ return;
+ }
+
+ CSize since_size;
+
+ since_->SetText(TimeFormat::RelativeDate(model_->start_time(), NULL));
+ since_->GetPreferredSize(&since_size);
+ since_->SetBounds(kLeftMargin, download_util::kBigProgressIconOffset,
+ kDateSize, since_size.cy);
+ since_->SetVisible(true);
+
+ CSize date_size;
+ date_->SetText(base::TimeFormatShortDate(model_->start_time()));
+ date_->GetPreferredSize(&date_size);
+ date_->SetBounds(kLeftMargin, since_size.cy + kVerticalPadding +
+ download_util::kBigProgressIconOffset,
+ kDateSize, date_size.cy);
+ date_->SetVisible(true);
+}
+
+// DownloadItem::COMPLETE state layout
+void DownloadItemTabView::LayoutComplete() {
+ // Hide unused UI elements
+ pause_->SetVisible(false);
+ pause_->SetEnabled(false);
+ cancel_->SetVisible(false);
+ cancel_->SetEnabled(false);
+ time_remaining_->SetVisible(false);
+ download_progress_->SetVisible(false);
+
+ LayoutDate();
+ int dx = kDownloadIconOffset - download_util::kBigProgressIconOffset +
+ download_util::kBigProgressIconSize + kInfoPadding;
+
+ // File name and URL
+ CSize file_name_size;
+ file_name_->SetText(model_->file_name());
+ file_name_->GetPreferredSize(&file_name_size);
+ file_name_->SetBounds(dx, download_util::kBigProgressIconOffset,
+ std::min(kFilenameSize,
+ static_cast<int>(file_name_size.cx)),
+ file_name_size.cy);
+ file_name_->SetVisible(true);
+ file_name_->SetEnabled(true);
+
+ GURL url(model_->url());
+ download_url_->SetURL(url);
+ CSize url_size;
+ download_url_->GetPreferredSize(&url_size);
+ download_url_->SetBounds(dx,
+ file_name_size.cy + kVerticalPadding +
+ download_util::kBigProgressIconOffset,
+ std::min(kFilenameSize,
+ static_cast<int>(GetWidth() - dx)),
+ url_size.cy);
+ download_url_->SetVisible(true);
+ dx += kFilenameSize + kSpacer;
+
+ // Action button (text is constant and set in constructor)
+ CSize show_size;
+ show_->GetPreferredSize(&show_size);
+ show_->SetBounds(dx, ((file_name_size.cy + url_size.cy) / 2) +
+ download_util::kBigProgressIconOffset,
+ show_size.cx, show_size.cy);
+ show_->SetVisible(true);
+ show_->SetEnabled(true);
+}
+
+// DownloadItem::CANCELLED state layout
+void DownloadItemTabView::LayoutCancelled() {
+ // Hide unused UI elements
+ show_->SetVisible(false);
+ show_->SetEnabled(false);
+ pause_->SetVisible(false);
+ pause_->SetEnabled(false);
+ cancel_->SetVisible(false);
+ cancel_->SetEnabled(false);
+
+ LayoutDate();
+ int dx = kDownloadIconOffset - download_util::kBigProgressIconOffset +
+ download_util::kBigProgressIconSize + kInfoPadding;
+
+ // File name and URL, truncated to show cancelled status
+ CSize file_name_size;
+ file_name_->SetText(model_->file_name());
+ file_name_->GetPreferredSize(&file_name_size);
+ file_name_->SetBounds(dx, download_util::kBigProgressIconOffset,
+ kFilenameSize - kProgressSize - kSpacer,
+ file_name_size.cy);
+ file_name_->SetVisible(true);
+ file_name_->SetEnabled(false);
+
+ GURL url(model_->url());
+ download_url_->SetURL(url);
+ CSize url_size;
+ download_url_->GetPreferredSize(&url_size);
+ download_url_->SetBounds(dx,
+ file_name_size.cy + kVerticalPadding +
+ download_util::kBigProgressIconOffset,
+ std::min(kFilenameSize - kProgressSize - kSpacer,
+ static_cast<int>(GetWidth() - dx)),
+ url_size.cy);
+ download_url_->SetVisible(true);
+
+ dx += kFilenameSize - kProgressSize;
+
+ // Display cancelled status
+ CSize cancel_size;
+ time_remaining_->SetColor(kStatusColor);
+ time_remaining_->SetText(l10n_util::GetString(IDS_DOWNLOAD_TAB_CANCELLED));
+ time_remaining_->GetPreferredSize(&cancel_size);
+ time_remaining_->SetBounds(dx, download_util::kBigProgressIconOffset,
+ kProgressSize, cancel_size.cy);
+ time_remaining_->SetVisible(true);
+
+ // Display received size, we may not know the total size if the server didn't
+ // provide a content-length.
+ int64 total = model_->total_bytes();
+ int64 size = model_->received_bytes();
+ DataUnits amount_units = GetByteDisplayUnits(size);
+ std::wstring received_size = FormatBytes(size, amount_units, true);
+ std::wstring amount = received_size;
+
+ // We don't know which string we'll end up using for constructing the final
+ // progress string so we need to adjust both strings for the locale
+ // direction.
+ std::wstring amount_localized;
+ if (l10n_util::AdjustStringForLocaleDirection(amount, &amount_localized)) {
+ amount.assign(amount_localized);
+ received_size.assign(amount_localized);
+ }
+
+ if (total > 0) {
+ amount_units = GetByteDisplayUnits(total);
+ std::wstring total_text = FormatBytes(total, amount_units, true);
+ std::wstring total_text_localized;
+ if (l10n_util::AdjustStringForLocaleDirection(total_text,
+ &total_text_localized))
+ total_text.assign(total_text_localized);
+
+ // Note that there is no need to adjust the new amount string for the
+ // locale direction as ChromeViews::Label does that for us.
+ amount = l10n_util::GetStringF(IDS_DOWNLOAD_TAB_PROGRESS_SIZE,
+ received_size,
+ total_text);
+ }
+
+ CSize byte_size;
+ download_progress_->SetText(amount);
+ download_progress_->GetPreferredSize(&byte_size);
+ download_progress_->SetBounds(dx,
+ file_name_size.cy + kVerticalPadding +
+ download_util::kBigProgressIconOffset,
+ kProgressSize,
+ byte_size.cy);
+ download_progress_->SetVisible(true);
+}
+
+// DownloadItem::IN_PROGRESS state layout
+void DownloadItemTabView::LayoutInProgress() {
+ // Hide unused UI elements
+ show_->SetVisible(false);
+ show_->SetEnabled(false);
+
+ LayoutDate();
+ int dx = kDownloadIconOffset - download_util::kBigProgressIconOffset +
+ download_util::kBigProgressIconSize +
+ kInfoPadding;
+
+ // File name and URL, truncated to show progress status
+ CSize file_name_size;
+ file_name_->SetText(model_->file_name());
+ file_name_->GetPreferredSize(&file_name_size);
+ file_name_->SetBounds(dx, download_util::kBigProgressIconOffset,
+ kFilenameSize - kProgressSize - kSpacer,
+ file_name_size.cy);
+ file_name_->SetVisible(true);
+ file_name_->SetEnabled(false);
+
+ GURL url(model_->url());
+ download_url_->SetURL(url);
+ CSize url_size;
+ download_url_->GetPreferredSize(&url_size);
+ download_url_->SetBounds(dx, file_name_size.cy + kVerticalPadding +
+ download_util::kBigProgressIconOffset,
+ std::min(kFilenameSize - kProgressSize - kSpacer,
+ static_cast<int>(GetWidth() - dx)),
+ url_size.cy);
+ download_url_->SetVisible(true);
+
+ dx += kFilenameSize - kProgressSize;
+
+ // Set the time remaining and progress display strings. This can
+ // be complicated by not having received the total download size
+ // In that case, we can't calculate time remaining so we just
+ // display speed and received size.
+
+ // Size
+ int64 total = model_->total_bytes();
+ int64 size = model_->received_bytes();
+ DataUnits amount_units = GetByteDisplayUnits(size);
+ std::wstring received_size = FormatBytes(size, amount_units, true);
+ std::wstring amount = received_size;
+
+ // Adjust both strings for the locale direction since we don't yet know which
+ // string we'll end up using for constructing the final progress string.
+ std::wstring amount_localized;
+ if (l10n_util::AdjustStringForLocaleDirection(amount, &amount_localized)) {
+ amount.assign(amount_localized);
+ received_size.assign(amount_localized);
+ }
+
+ if (total > 0) {
+ amount_units = GetByteDisplayUnits(total);
+ std::wstring total_text = FormatBytes(total, amount_units, true);
+ std::wstring total_text_localized;
+ if (l10n_util::AdjustStringForLocaleDirection(total_text,
+ &total_text_localized))
+ total_text.assign(total_text_localized);
+
+ amount = l10n_util::GetStringF(IDS_DOWNLOAD_TAB_PROGRESS_SIZE,
+ received_size,
+ total_text);
+
+ // We adjust the 'amount' string in case we use it as part of the progress
+ // text.
+ if (l10n_util::AdjustStringForLocaleDirection(amount, &amount_localized))
+ amount.assign(amount_localized);
+ }
+
+ // Speed
+ int64 speed = model_->CurrentSpeed();
+ std::wstring progress = amount;
+ if (!model_->is_paused() && speed > 0) {
+ amount_units = GetByteDisplayUnits(speed);
+ std::wstring speed_text = FormatSpeed(speed, amount_units, true);
+ std::wstring speed_text_localized;
+ if (l10n_util::AdjustStringForLocaleDirection(speed_text,
+ &speed_text_localized))
+ speed_text.assign(speed_text_localized);
+
+ progress = l10n_util::GetStringF(IDS_DOWNLOAD_TAB_PROGRESS_SPEED,
+ speed_text,
+ amount);
+
+ // For some reason, the appearance of the dash character ('-') in a string
+ // causes Windows to ignore the 'LRE'/'RLE'/'PDF' Unicode formatting
+ // characters within the string and this causes the string to be displayed
+ // incorrectly on RTL UIs. Therefore, we add the Unicode right-to-left
+ // override character (U+202E) if the locale is RTL in order to fix this
+ // problem.
+ if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT)
+ progress.insert(0, L"\x202E");
+ }
+
+ // Time remaining
+ int y_pos = file_name_size.cy + kVerticalPadding +
+ download_util::kBigProgressIconOffset;
+ CSize time_size;
+ time_remaining_->SetColor(kStatusColor);
+ if (model_->is_paused()) {
+ time_remaining_->SetColor(kPauseColor);
+ time_remaining_->SetText(
+ l10n_util::GetString(IDS_DOWNLOAD_PROGRESS_PAUSED));
+ time_remaining_->GetPreferredSize(&time_size);
+ time_remaining_->SetBounds(dx, download_util::kBigProgressIconOffset,
+ kProgressSize, time_size.cy);
+ time_remaining_->SetVisible(true);
+ } else if (total > 0) {
+ TimeDelta remaining;
+ if (model_->TimeRemaining(&remaining))
+ time_remaining_->SetText(TimeFormat::TimeRemaining(remaining));
+ time_remaining_->GetPreferredSize(&time_size);
+ time_remaining_->SetBounds(dx, download_util::kBigProgressIconOffset,
+ kProgressSize, time_size.cy);
+ time_remaining_->SetVisible(true);
+ } else {
+ time_remaining_->SetText(L"");
+ y_pos = ((file_name_size.cy + url_size.cy) / 2) +
+ download_util::kBigProgressIconOffset;
+ }
+
+ CSize byte_size;
+ download_progress_->SetText(progress);
+ download_progress_->GetPreferredSize(&byte_size);
+ download_progress_->SetBounds(dx, y_pos,
+ kProgressSize, byte_size.cy);
+ download_progress_->SetVisible(true);
+
+ dx += kProgressSize + kSpacer;
+ y_pos = ((file_name_size.cy + url_size.cy) / 2) +
+ download_util::kBigProgressIconOffset;
+
+ // Pause (or Resume) / Cancel buttons.
+ if (model_->is_paused())
+ pause_->SetText(l10n_util::GetString(IDS_DOWNLOAD_LINK_RESUME));
+ else
+ pause_->SetText(l10n_util::GetString(IDS_DOWNLOAD_LINK_PAUSE));
+
+ CSize pause_size;
+ pause_->SetVisible(true);
+ pause_->SetEnabled(true);
+ pause_->GetPreferredSize(&pause_size);
+ pause_->SetBounds(dx, y_pos, pause_size.cx, pause_size.cy);
+
+ dx += pause_size.cx + kHorizontalButtonPadding;
+
+ CSize cancel_size;
+ cancel_->GetPreferredSize(&cancel_size);
+ cancel_->SetBounds(dx, y_pos, cancel_size.cx, cancel_size.cy);
+ cancel_->SetVisible(true);
+ cancel_->SetEnabled(true);
+}
+
+void DownloadItemTabView::Paint(ChromeCanvas* canvas) {
+ PaintBackground(canvas);
+
+ if (model_->state() == DownloadItem::IN_PROGRESS) {
+ download_util::PaintDownloadProgress(canvas,
+ this,
+ kDownloadIconOffset -
+ download_util::kBigProgressIconOffset,
+ 0,
+ parent_->start_angle(),
+ model_->PercentComplete(),
+ download_util::BIG);
+ }
+
+ // Most of the UI elements in the DownloadItemTabView are represented as
+ // child Views and therefore they get mirrored automatically in
+ // right-to-left UIs. The download item icon is not contained within a child
+ // View so we need to mirror it manually if the locale is RTL.
+ SkBitmap* icon = parent_->LookupIcon(model_);
+ if (icon) {
+ gfx::Rect icon_bounds(kDownloadIconOffset,
+ download_util::kBigProgressIconOffset,
+ icon->width(), icon->height());
+ icon_bounds.set_x(MirroredLeftPointForRect(icon_bounds));
+ canvas->DrawBitmapInt(*icon, icon_bounds.x(), icon_bounds.y());
+ }
+}
+
+void DownloadItemTabView::PaintBackground(ChromeCanvas* canvas) {
+ if (parent_->ItemIsSelected(model_)) {
+ // Before we paint the border and the focus rect, we need to mirror the
+ // highlighted area if the View is using a right-to-left UI layout. We need
+ // to explicitly mirror the position because the highlighted area is
+ // directly painted on the canvas (as opposed to being represented as a
+ // child View like the rest of the UI elements in DownloadItemTabView).
+ gfx::Rect highlighted_bounds(kDownloadIconOffset -
+ download_util::kBigProgressIconOffset,
+ 0,
+ download_util::kBigProgressIconSize +
+ kInfoPadding + kFilenameSize,
+ download_util::kBigProgressIconSize);
+ highlighted_bounds.set_x(MirroredLeftPointForRect(highlighted_bounds));
+
+ canvas->FillRectInt(kSelectedItemColor,
+ highlighted_bounds.x(),
+ highlighted_bounds.y(),
+ highlighted_bounds.width(),
+ highlighted_bounds.height());
+
+ canvas->DrawFocusRect(highlighted_bounds.x(),
+ highlighted_bounds.y(),
+ highlighted_bounds.width(),
+ highlighted_bounds.height());
+ }
+}
+
+void DownloadItemTabView::DidChangeBounds(const CRect& previous,
+ const CRect& current) {
+ Layout();
+}
+
+bool DownloadItemTabView::OnMousePressed(const ChromeViews::MouseEvent& event) {
+ CPoint point(event.GetX(), event.GetY());
+
+ // If the click is in the highlight region, then highlight this download.
+ // Otherwise, remove the highlighting from any download.
+ CRect select_rect(kDownloadIconOffset - download_util::kBigProgressIconOffset,
+ 0,
+ kDownloadIconOffset -
+ download_util::kBigProgressIconOffset +
+ download_util::kBigProgressIconSize + kInfoPadding +
+ kFilenameSize,
+ download_util::kBigProgressIconSize);
+
+ // The position of the highlighted region does not take into account the
+ // View's UI layout so we have to manually mirror the position if the View is
+ // using a right-to-left UI layout.
+ gfx::Rect mirrored_rect(select_rect);
+ select_rect.MoveToX(MirroredLeftPointForRect(mirrored_rect));
+ if (select_rect.PtInRect(point)) {
+ parent_->ItemBecameSelected(model_);
+
+ if (event.IsRightMouseButton()) {
+ ChromeViews::View::ConvertPointToScreen(this, &point);
+
+ download_util::DownloadDestinationContextMenu menu(
+ model_, GetViewContainer()->GetHWND(), point);
+ }
+ } else {
+ parent_->ItemBecameSelected(NULL);
+ }
+
+ return true;
+}
+
+// Handle drag (file copy) operations.
+bool DownloadItemTabView::OnMouseDragged(const ChromeViews::MouseEvent& event) {
+ if (model_->state() != DownloadItem::COMPLETE)
+ return false;
+
+ CPoint point(event.GetX(), event.GetY());
+
+ // In order to make sure drag and drop works as expected when the UI is
+ // mirrored, we can either flip the mouse X coordinate or flip the X position
+ // of the drag rectangle. Flipping the mouse X coordinate is easier.
+ point.x = MirroredXCoordinateInsideView(point.x);
+ CRect drag_rect(kDownloadIconOffset - download_util::kBigProgressIconOffset,
+ 0,
+ kDownloadIconOffset - download_util::kBigProgressIconOffset +
+ download_util::kBigProgressIconSize + kInfoPadding +
+ kFilenameSize,
+ download_util::kBigProgressIconSize);
+
+ if (drag_rect.PtInRect(point)) {
+ SkBitmap* icon = parent_->LookupIcon(model_);
+ if (icon)
+ download_util::DragDownload(model_, icon);
+ }
+
+ return true;
+}
+
+void DownloadItemTabView::LinkActivated(ChromeViews::Link* source,
+ int event_flags) {
+ // There are several links in our view that could have been clicked:
+ if (source == file_name_) {
+ ChromeViews::ViewContainer* container = this->GetViewContainer();
+ HWND parent_window = container ? container->GetHWND() : NULL;
+ model_->manager()->OpenDownloadInShell(model_, parent_window);
+ } else if (source == pause_) {
+ model_->TogglePause();
+ } else if (source == cancel_) {
+ model_->Cancel(true /* update history service */);
+ } else if (source == show_) {
+ model_->manager()->ShowDownloadInShell(model_);
+ } else {
+ NOTREACHED();
+ }
+
+ parent_->ItemBecameSelected(model_);
+}
+
+
+// DownloadTabView implementation ----------------------------------------------
+
+DownloadTabView::DownloadTabView(DownloadManager* model)
+ : model_(model),
+ start_angle_(download_util::kStartAngleDegrees),
+ scroll_helper_(kSpacer, download_util::kBigProgressIconSize + kSpacer),
+ selected_index_(-1) {
+ DCHECK(model_);
+}
+
+DownloadTabView::~DownloadTabView() {
+ StopDownloadProgress();
+ model_->RemoveObserver(this);
+
+ // DownloadManager owns the contents.
+ downloads_.clear();
+ ClearDownloadInProgress();
+
+ icon_consumer_.CancelAllRequests();
+}
+
+void DownloadTabView::Initialize() {
+ model_->AddObserver(this);
+}
+
+// Start progress animation timers when we get our first (in-progress) download.
+void DownloadTabView::StartDownloadProgress() {
+ if (progress_timer_.IsRunning())
+ return;
+ progress_timer_.Start(
+ TimeDelta::FromMilliseconds(download_util::kProgressRateMs), this,
+ &DownloadTabView::UpdateDownloadProgress);
+}
+
+// Stop progress animation when there are no more in-progress downloads.
+void DownloadTabView::StopDownloadProgress() {
+ progress_timer_.Stop();
+}
+
+// Update our animations.
+void DownloadTabView::UpdateDownloadProgress() {
+ start_angle_ = (start_angle_ + download_util::kUnknownIncrementDegrees) %
+ download_util::kMaxDegrees;
+ SchedulePaint();
+}
+
+void DownloadTabView::DidChangeBounds(const CRect& previous,
+ const CRect& current) {
+ Layout();
+}
+
+void DownloadTabView::Layout() {
+ CRect r;
+ DetachAllFloatingViews();
+ View* v = GetParent();
+ if (v) {
+ v->GetLocalBounds(&r, true);
+ int x = GetX();
+ int y = GetY();
+ int w = v->GetWidth();
+ int h = static_cast<int>(downloads_.size()) *
+ (download_util::kBigProgressIconSize + kSpacer) + kSpacer;
+ SetBounds(x, y, w, h);
+ }
+}
+
+// Paint our scrolled region
+void DownloadTabView::Paint(ChromeCanvas* canvas) {
+ ChromeViews::View::Paint(canvas);
+
+ if (download_util::kBigIconSize == 0 || downloads_.size() == 0)
+ return;
+
+ SkRect clip;
+ if (canvas->getClipBounds(&clip)) {
+ int row_start = (SkScalarRound(clip.fTop) - kSpacer) /
+ (download_util::kBigProgressIconSize + kSpacer);
+ int row_stop = SkScalarRound(clip.fBottom) /
+ (download_util::kBigProgressIconSize + kSpacer);
+ SkRect download_rect;
+ for (int i = row_start; i <= row_stop; ++i) {
+ int y = i * (download_util::kBigProgressIconSize + kSpacer) + kSpacer;
+ if (HasFloatingViewForPoint(0, y))
+ continue;
+ download_rect.set(SkIntToScalar(0),
+ SkIntToScalar(y),
+ SkIntToScalar(GetWidth()),
+ SkIntToScalar(y + download_util::kBigProgressIconSize));
+ if (SkRect::Intersects(clip, download_rect)) {
+ // The DownloadManager stores downloads earliest first, but this
+ // view displays latest first, so adjust the index:
+ int index = static_cast<int>(downloads_.size()) - 1 - i;
+ download_renderer_.SetModel(downloads_[index], this);
+ PaintFloatingView(canvas, &download_renderer_,
+ 0, y,
+ GetWidth(), download_util::kBigProgressIconSize);
+ }
+ }
+ }
+}
+
+// Draw the DownloadItemTabView for the current position.
+bool DownloadTabView::GetFloatingViewIDForPoint(int x, int y, int* id) {
+ if (y < kSpacer ||
+ y > (kSpacer + download_util::kBigProgressIconSize) *
+ static_cast<int>(downloads_.size()))
+ return false;
+
+ // Are we hovering over a download or the spacer? If we're over the
+ // download, create a floating view for it.
+ if ((y - kSpacer) % (download_util::kBigProgressIconSize + kSpacer) <
+ download_util::kBigProgressIconSize) {
+ int row = y / (download_util::kBigProgressIconSize + kSpacer);
+ *id = static_cast<int>(downloads_.size()) - 1 - row;
+ return true;
+ }
+ return false;
+}
+
+ChromeViews::View* DownloadTabView::CreateFloatingViewForIndex(int index) {
+ if (index >= static_cast<int>(downloads_.size())) {
+ // It's possible that the downloads have been cleared via the "Clear
+ // Browsing Data" command, so this index is gone.
+ return NULL;
+ }
+
+ DownloadItemTabView* dl = new DownloadItemTabView();
+ dl->SetModel(downloads_[index], this);
+ int row = static_cast<int>(downloads_.size()) - 1 - index;
+ int y_pos = row * (download_util::kBigProgressIconSize + kSpacer) + kSpacer;
+ dl->SetBounds(0, y_pos, GetWidth(), download_util::kBigProgressIconSize);
+ dl->Layout();
+ AttachFloatingView(dl, index);
+ return dl;
+}
+
+bool DownloadTabView::EnumerateFloatingViews(
+ ChromeViews::View::FloatingViewPosition position,
+ int starting_id, int* id) {
+ DCHECK(id);
+ return View::EnumerateFloatingViewsForInterval(
+ 0, static_cast<int>(downloads_.size()), false, position, starting_id, id);
+}
+
+ChromeViews::View* DownloadTabView::ValidateFloatingViewForID(int id) {
+ return CreateFloatingViewForIndex(id);
+}
+
+void DownloadTabView::OnDownloadUpdated(DownloadItem* download) {
+ switch (download->state()) {
+ case DownloadItem::COMPLETE:
+ case DownloadItem::CANCELLED: {
+ base::hash_set<DownloadItem*>::iterator d = in_progress_.find(download);
+ if (d != in_progress_.end()) {
+ (*d)->RemoveObserver(this);
+ in_progress_.erase(d);
+ }
+ if (in_progress_.empty())
+ StopDownloadProgress();
+ LoadIcon(download);
+ break;
+ }
+ case DownloadItem::IN_PROGRESS: {
+ // If all IN_PROGRESS downloads are paused, don't waste CPU issuing any
+ // further progress updates until at least one download is active again.
+ if (download->is_paused()) {
+ bool continue_update = false;
+ base::hash_set<DownloadItem*>::iterator it = in_progress_.begin();
+ for (; it != in_progress_.end(); ++it) {
+ if (!(*it)->is_paused()) {
+ continue_update = true;
+ break;
+ }
+ }
+ if (!continue_update)
+ StopDownloadProgress();
+ } else {
+ StartDownloadProgress();
+ }
+ break;
+ }
+ case DownloadItem::REMOVING:
+ // Handled below.
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ OrderedDownloads::iterator it = find(downloads_.begin(),
+ downloads_.end(),
+ download);
+ if (it == downloads_.end())
+ return;
+
+ const int index = static_cast<int>(it - downloads_.begin());
+ DownloadItemTabView* view =
+ static_cast<DownloadItemTabView*>(RetrieveFloatingViewForID(index));
+ if (view) {
+ if (download->state() != DownloadItem::REMOVING) {
+ view->Layout();
+ SchedulePaintForViewAtIndex(index);
+ } else if (selected_index_ == index) {
+ selected_index_ = -1;
+ }
+ }
+}
+
+// A download has started or been deleted. Query our DownloadManager for the
+// current set of downloads, which will call us back in SetDownloads once it
+// has retrieved them.
+void DownloadTabView::ModelChanged() {
+ downloads_.clear();
+ ClearDownloadInProgress();
+ DetachAllFloatingViews();
+
+ // Issue the query.
+ model_->GetDownloads(this, search_text_);
+}
+
+void DownloadTabView::SetDownloads(std::vector<DownloadItem*>& downloads) {
+ // Stop progress timers.
+ StopDownloadProgress();
+
+ // Clear out old state and remove self as observer for each download.
+ downloads_.clear();
+ ClearDownloadInProgress();
+
+ // Swap new downloads in.
+ downloads_.swap(downloads);
+ sort(downloads_.begin(), downloads_.end(), DownloadItemSorter());
+
+ // Scan for any in progress downloads and add ourself to them as an observer.
+ for (OrderedDownloads::iterator it = downloads_.begin();
+ it != downloads_.end(); ++it) {
+ DownloadItem* download = *it;
+ if (download->state() == DownloadItem::IN_PROGRESS) {
+ download->AddObserver(this);
+ in_progress_.insert(download);
+ }
+ }
+
+ // Start any progress timers if required.
+ if (!in_progress_.empty())
+ StartDownloadProgress();
+
+ // Update the UI.
+ selected_index_ = -1;
+ GetParent()->GetParent()->Layout();
+ SchedulePaint();
+}
+
+
+// If we have the icon in our cache, then return it. If not, look it up via the
+// IconManager. Ignore in progress requests (duplicates).
+SkBitmap* DownloadTabView::LookupIcon(DownloadItem* download) {
+ IconManager* im = g_browser_process->icon_manager();
+ // Fast look up.
+ SkBitmap* icon = im->LookupIcon(download->full_path(), IconLoader::NORMAL);
+
+ // Expensive look up.
+ if (!icon)
+ LoadIcon(download);
+
+ return icon;
+}
+
+// Bypass the caches and perform the Icon extraction directly. This is useful in
+// the case where the download has completed and we want to re-check the file
+// to see if it has an embedded icon (which we couldn't do at download start).
+void DownloadTabView::LoadIcon(DownloadItem* download) {
+ IconManager* im = g_browser_process->icon_manager();
+ IconManager::Handle h =
+ im->LoadIcon(download->full_path(), IconLoader::NORMAL,
+ &icon_consumer_,
+ NewCallback(this, &DownloadTabView::OnExtractIconComplete));
+ icon_consumer_.SetClientData(im, h, download);
+}
+
+void DownloadTabView::ClearDownloadInProgress() {
+ for (base::hash_set<DownloadItem*>::iterator it = in_progress_.begin();
+ it != in_progress_.end(); ++it)
+ (*it)->RemoveObserver(this);
+ in_progress_.clear();
+}
+
+// Check to see if the download is the latest download on a given day.
+// We use this to determine when to draw the date next to a particular
+// download view: if the DownloadItem is the latest download on a given
+// day, the date gets drawn.
+bool DownloadTabView::ShouldDrawDateForDownload(DownloadItem* download) {
+ DCHECK(download);
+ OrderedDownloads::iterator it = find(downloads_.begin(),
+ downloads_.end(),
+ download);
+ DCHECK(it != downloads_.end());
+ const int index = static_cast<int>(it - downloads_.begin());
+
+ // If download is the last or only download, it draws the date.
+ if (downloads_.size() - 1 == index)
+ return true;
+
+ const DownloadItem* next = downloads_[index + 1];
+
+ Time next_midnight = next->start_time().LocalMidnight();
+ Time curr_midnight = download->start_time().LocalMidnight();
+ if (next_midnight == curr_midnight) {
+ // 'next' happened today: let it draw the date so we don't have to.
+ return false;
+ }
+ return true;
+}
+
+int DownloadTabView::GetPageScrollIncrement(
+ ChromeViews::ScrollView* scroll_view, bool is_horizontal,
+ bool is_positive) {
+ return scroll_helper_.GetPageScrollIncrement(scroll_view, is_horizontal,
+ is_positive);
+}
+
+int DownloadTabView::GetLineScrollIncrement(
+ ChromeViews::ScrollView* scroll_view, bool is_horizontal,
+ bool is_positive) {
+ return scroll_helper_.GetLineScrollIncrement(scroll_view, is_horizontal,
+ is_positive);
+}
+
+void DownloadTabView::ItemBecameSelected(const DownloadItem* download) {
+ int index = -1;
+ if (download != NULL) {
+ OrderedDownloads::const_iterator it = find(downloads_.begin(),
+ downloads_.end(),
+ download);
+ DCHECK(it != downloads_.end());
+ index = static_cast<int>(it - downloads_.begin());
+ if (index == selected_index_)
+ return; // Avoid unnecessary paint.
+ }
+
+ if (selected_index_ >= 0)
+ SchedulePaintForViewAtIndex(selected_index_);
+ if (index >= 0)
+ SchedulePaintForViewAtIndex(index);
+ selected_index_ = index;
+}
+
+bool DownloadTabView::ItemIsSelected(DownloadItem* download) {
+ OrderedDownloads::iterator it = find(downloads_.begin(),
+ downloads_.end(),
+ download);
+ if (it != downloads_.end())
+ return selected_index_ == static_cast<int>(it - downloads_.begin());
+ return false;
+}
+
+void DownloadTabView::SchedulePaintForViewAtIndex(int index) {
+ int y = GetYPositionForIndex(index);
+ SchedulePaint(0, y, GetWidth(), download_util::kBigProgressIconSize);
+}
+
+int DownloadTabView::GetYPositionForIndex(int index) {
+ int row = static_cast<int>(downloads_.size()) - 1 - index;
+ return row * (download_util::kBigProgressIconSize + kSpacer) + kSpacer;
+}
+
+void DownloadTabView::SetSearchText(const std::wstring& search_text) {
+ search_text_ = search_text;
+ model_->GetDownloads(this, search_text_);
+}
+
+// The 'icon_bitmap' is ignored here, since it is cached by the IconManager.
+// When the paint message runs, we'll use the fast IconManager lookup API to
+// retrieve it.
+void DownloadTabView::OnExtractIconComplete(IconManager::Handle handle,
+ SkBitmap* icon_bitmap) {
+ IconManager* im = g_browser_process->icon_manager();
+ DownloadItem* download = icon_consumer_.GetClientData(im, handle);
+ OrderedDownloads::iterator it = find(downloads_.begin(),
+ downloads_.end(),
+ download);
+ if (it != downloads_.end()) {
+ const int index = static_cast<int>(it - downloads_.begin());
+ SchedulePaintForViewAtIndex(index);
+ }
+}
+
+// DownloadTabUIFactory ------------------------------------------------------
+
+class DownloadTabUIFactory : public NativeUIFactory {
+ public:
+ DownloadTabUIFactory() {}
+ virtual ~DownloadTabUIFactory() {}
+
+ virtual NativeUI* CreateNativeUIForURL(const GURL& url,
+ NativeUIContents* contents) {
+ return new DownloadTabUI(contents);
+ }
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(DownloadTabUIFactory);
+};
+
+// DownloadTabUI -------------------------------------------------------------
+
+DownloadTabUI::DownloadTabUI(NativeUIContents* contents)
+#pragma warning(suppress: 4355) // Okay to pass "this" here.
+ : searchable_container_(this),
+ download_tab_view_(NULL),
+ contents_(contents) {
+ DownloadManager* dlm = contents_->profile()->GetDownloadManager();
+ download_tab_view_ = new DownloadTabView(dlm);
+ searchable_container_.SetContents(download_tab_view_);
+ download_tab_view_->Initialize();
+
+ NotificationService* ns = NotificationService::current();
+ ns->AddObserver(this, NOTIFY_DOWNLOAD_START,
+ NotificationService::AllSources());
+ ns->AddObserver(this, NOTIFY_DOWNLOAD_STOP,
+ NotificationService::AllSources());
+
+ // Spin the throbber if there are active downloads, since we may have been
+ // created after the NOTIFY_DOWNLOAD_START was sent. If the download manager
+ // has not been created, don't bother since it will negatively impact start
+ // up time with history requests.
+ Profile* profile = contents_->profile();
+ if (profile &&
+ profile->HasCreatedDownloadManager() &&
+ profile->GetDownloadManager()->in_progress_count() > 0)
+ contents_->SetIsLoading(true, NULL);
+}
+
+DownloadTabUI::~DownloadTabUI() {
+ NotificationService* ns = NotificationService::current();
+ ns->RemoveObserver(this, NOTIFY_DOWNLOAD_START,
+ NotificationService::AllSources());
+ ns->RemoveObserver(this, NOTIFY_DOWNLOAD_STOP,
+ NotificationService::AllSources());
+}
+
+const std::wstring DownloadTabUI::GetTitle() const {
+ return l10n_util::GetString(IDS_DOWNLOAD_TITLE);
+}
+
+const int DownloadTabUI::GetFavIconID() const {
+ return IDR_DOWNLOADS_FAVICON;
+}
+
+const int DownloadTabUI::GetSectionIconID() const {
+ return IDR_DOWNLOADS_SECTION;
+}
+
+const std::wstring DownloadTabUI::GetSearchButtonText() const {
+ return l10n_util::GetString(IDS_DOWNLOAD_SEARCH_BUTTON);
+}
+
+ChromeViews::View* DownloadTabUI::GetView() {
+ return &searchable_container_;
+}
+
+void DownloadTabUI::WillBecomeVisible(NativeUIContents* parent) {
+ UserMetrics::RecordAction(L"Destination_Downloads", parent->profile());
+}
+
+void DownloadTabUI::WillBecomeInvisible(NativeUIContents* parent) {
+}
+
+void DownloadTabUI::Navigate(const PageState& state) {
+ std::wstring search_text;
+ state.GetProperty(kSearchTextKey, &search_text);
+ download_tab_view_->SetSearchText(search_text);
+ searchable_container_.GetSearchField()->SetText(search_text);
+}
+
+bool DownloadTabUI::SetInitialFocus() {
+ searchable_container_.GetSearchField()->RequestFocus();
+ return true;
+}
+
+// static
+GURL DownloadTabUI::GetURL() {
+ std::string spec(NativeUIContents::GetScheme());
+ spec.append("://downloads");
+ return GURL(spec);
+}
+
+// static
+NativeUIFactory* DownloadTabUI::GetNativeUIFactory() {
+ return new DownloadTabUIFactory();
+}
+
+void DownloadTabUI::DoSearch(const std::wstring& new_text) {
+ download_tab_view_->SetSearchText(new_text);
+ PageState* page_state = contents_->page_state().Copy();
+ page_state->SetProperty(kSearchTextKey, new_text);
+ contents_->SetPageState(page_state);
+}
+
+void DownloadTabUI::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ switch (type) {
+ case NOTIFY_DOWNLOAD_START:
+ case NOTIFY_DOWNLOAD_STOP:
+ DCHECK(profile()->HasCreatedDownloadManager());
+ contents_->SetIsLoading(
+ profile()->GetDownloadManager()->in_progress_count() > 0,
+ NULL);
+ break;
+ default:
+ break;
+ }
+}
+
diff --git a/chrome/browser/views/download_tab_view.h b/chrome/browser/views/download_tab_view.h
new file mode 100644
index 0000000..5c1b2ec
--- /dev/null
+++ b/chrome/browser/views/download_tab_view.h
@@ -0,0 +1,252 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_VIEWS_DONWLOAD_TAB_VIEW_H__
+#define CHROME_BROWSER_VIEWS_DONWLOAD_TAB_VIEW_H__
+
+#include "base/hash_tables.h"
+#include "chrome/browser/cancelable_request.h"
+#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/icon_manager.h"
+#include "chrome/browser/native_ui_contents.h"
+#include "chrome/views/event.h"
+#include "chrome/views/label.h"
+#include "chrome/views/link.h"
+#include "chrome/views/scroll_view.h"
+
+class DownloadTabView;
+class SkBitmap;
+class Task;
+
+namespace base {
+class Timer;
+}
+
+class DownloadItemTabView : public ChromeViews::View,
+ public ChromeViews::LinkController {
+ public:
+ DownloadItemTabView();
+ virtual ~DownloadItemTabView();
+
+ // View overrides
+ virtual void Layout();
+ virtual void Paint(ChromeCanvas* canvas);
+ void PaintBackground(ChromeCanvas* canvas);
+ virtual void GetPreferredSize(CSize* out);
+ virtual void DidChangeBounds(const CRect& previous, const CRect& current);
+ virtual bool OnMousePressed(const ChromeViews::MouseEvent& event);
+ virtual bool OnMouseDragged(const ChromeViews::MouseEvent& event);
+
+ // Mode specific layouts
+ void LayoutDate();
+ void LayoutComplete();
+ void LayoutCancelled();
+ void LayoutInProgress();
+
+ // LinkController overrides
+ virtual void LinkActivated(ChromeViews::Link* source, int event_flags);
+
+ // Used to set our model temporarily during layout and paint operations
+ void SetModel(DownloadItem* model, DownloadTabView* parent);
+
+private:
+ // Our model.
+ DownloadItem* model_;
+
+ // Containing view.
+ DownloadTabView* parent_;
+
+ // Time display.
+ ChromeViews::Label* since_;
+ ChromeViews::Label* date_;
+
+ // The name of the file. Clicking this link will open the download.
+ ChromeViews::Link* file_name_;
+
+ // The name of the downloaded URL.
+ ChromeViews::Label* download_url_;
+
+ // The current status of the download.
+ ChromeViews::Label* time_remaining_;
+ ChromeViews::Label* download_progress_;
+
+ // Actions that can be initiated.
+ ChromeViews::Link* pause_;
+ ChromeViews::Link* cancel_;
+ ChromeViews::Link* show_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DownloadItemTabView);
+};
+
+
+// A view that manages each of the individual download views
+// (DownloadItemTabView) in the destination tab.
+class DownloadTabView : public ChromeViews::View,
+ public DownloadItem::Observer,
+ public DownloadManager::Observer {
+ public:
+ DownloadTabView(DownloadManager* model);
+ ~DownloadTabView();
+
+ void Initialize();
+
+ DownloadManager* model() const { return model_; }
+
+ // View overrides
+ virtual void DidChangeBounds(const CRect& previous, const CRect& current);
+ virtual void Layout();
+ virtual void Paint(ChromeCanvas* canvas);
+ virtual bool GetFloatingViewIDForPoint(int x, int y, int* id);
+ virtual bool EnumerateFloatingViews(
+ ChromeViews::View::FloatingViewPosition position,
+ int starting_id, int* id);
+ virtual ChromeViews::View* ValidateFloatingViewForID(int id);
+
+ // DownloadItem::Observer interface
+ virtual void OnDownloadUpdated(DownloadItem* download);
+
+ // DownloadManager::Observer interface
+ virtual void ModelChanged();
+ virtual void SetDownloads(std::vector<DownloadItem*>& downloads);
+
+ // IconManager callback interface
+ void OnExtractIconComplete(IconManager::Handle handle, SkBitmap* icon_bitmap);
+
+ // Progress animation task interface and timer management.
+ void UpdateDownloadProgress();
+ void StartDownloadProgress();
+ void StopDownloadProgress();
+
+ // Returns a non owning pointer to an icon in the icon_cache_. If
+ // that file extension doesn't exist in our cache, we query Windows
+ // and add it to our cache. Returns NULL if we can't determine the
+ // icon.
+ SkBitmap* LookupIcon(DownloadItem* download);
+
+ // Determine if we should draw the date beside a particular download
+ bool ShouldDrawDateForDownload(DownloadItem* download);
+
+ virtual int GetPageScrollIncrement(ChromeViews::ScrollView* scroll_view,
+ bool is_horizontal, bool is_positive);
+ virtual int GetLineScrollIncrement(ChromeViews::ScrollView* scroll_view,
+ bool is_horizontal, bool is_positive);
+
+ int start_angle() const { return start_angle_; }
+
+ // Called by a DownloadItemTabView when it becomes selected. Passing a NULL
+ // for 'download' causes any selected download to become unselected.
+ void ItemBecameSelected(const DownloadItem* download);
+ bool ItemIsSelected(DownloadItem* download);
+
+ // The destination view's search box text has changed.
+ void SetSearchText(const std::wstring& search_text);
+
+ private:
+ // Creates and attaches to the view the floating view at |index|.
+ ChromeViews::View* CreateFloatingViewForIndex(int index);
+
+ // Utility functions for operating on DownloadItemTabViews by index.
+ void SchedulePaintForViewAtIndex(int index);
+ int GetYPositionForIndex(int index);
+
+ // Initiates an asynchronous icon extraction.
+ void LoadIcon(DownloadItem* download);
+
+ // Clears the list of "in progress" downloads and removes the this
+ // DownloadTabView from their observer list.
+ void ClearDownloadInProgress();
+
+ // Our model
+ DownloadManager* model_;
+
+ // For drawing individual download items
+ DownloadItemTabView download_renderer_;
+
+ // The current set of visible DownloadItems for this view received from the
+ // DownloadManager. DownloadManager owns the DownloadItems. The vector is
+ // kept in order, sorted by ascending start time.
+ typedef std::vector<DownloadItem*> OrderedDownloads;
+ OrderedDownloads downloads_;
+
+ // Progress animations
+ base::RepeatingTimer<DownloadTabView> progress_timer_;
+
+ // Since this view manages the progress animation timers for all the floating
+ // views, we need to track the current in progress downloads. This container
+ // does not own the DownloadItems.
+ base::hash_set<DownloadItem*> in_progress_;
+
+ // Provide a start position for downloads with no known size.
+ int start_angle_;
+
+ ChromeViews::FixedRowHeightScrollHelper scroll_helper_;
+
+ // Keep track of the currently selected view, so that we can inform it when
+ // the user changes the selection.
+ int selected_index_;
+
+ // Text in the download search box input by the user.
+ std::wstring search_text_;
+
+ // For requesting icons from the IconManager.
+ CancelableRequestConsumerT<DownloadItem*, 0> icon_consumer_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DownloadTabView);
+};
+
+// DownloadTabUI -------------------------------------------------------------
+
+// DownloadTabUI provides the glue to make DownloadTabView available in
+// NativeUIContents.
+
+class DownloadTabUI : public NativeUI,
+ public SearchableUIContainer::Delegate,
+ public NotificationObserver {
+ public:
+ explicit DownloadTabUI(NativeUIContents* contents);
+ virtual ~DownloadTabUI();
+
+ virtual const std::wstring GetTitle() const;
+ virtual const int GetFavIconID() const;
+ virtual const int GetSectionIconID() const;
+ virtual const std::wstring GetSearchButtonText() const;
+ virtual ChromeViews::View* GetView();
+ virtual void WillBecomeVisible(NativeUIContents* parent);
+ virtual void WillBecomeInvisible(NativeUIContents* parent);
+ virtual void Navigate(const PageState& state);
+ virtual bool SetInitialFocus();
+
+ // Return the URL that can be used to show this view in a NativeUIContents.
+ static GURL GetURL();
+
+ // Return the NativeUIFactory object for application views. This object is
+ // owned by the caller.
+ static NativeUIFactory* GetNativeUIFactory();
+
+ private:
+ // Sent from the search box, updates the search text appropriately.
+ virtual void DoSearch(const std::wstring& new_text);
+
+ // NotificationObserver method, updates loading state based on whether
+ // any downloads are in progress.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ Profile* profile() const { return contents_->profile(); }
+
+ // Our host.
+ NativeUIContents* contents_;
+
+ // The view we return from GetView. The contents of this is the
+ // bookmarks_view_
+ SearchableUIContainer searchable_container_;
+
+ DownloadTabView* download_tab_view_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DownloadTabUI);
+};
+
+#endif // CHROME_BROWSER_VIEWS_DONWLOAD_TAB_VIEW_H__
diff --git a/chrome/browser/views/options/advanced_contents_view.cc b/chrome/browser/views/options/advanced_contents_view.cc
index 1bb4343..569ca31 100644
--- a/chrome/browser/views/options/advanced_contents_view.cc
+++ b/chrome/browser/views/options/advanced_contents_view.cc
@@ -19,7 +19,7 @@
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/download_manager.h"
+#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/gears_integration.h"
#include "chrome/browser/metrics_service.h"
#include "chrome/browser/net/dns_global.h"