diff options
author | paulg@google.com <paulg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-13 02:48:59 +0000 |
---|---|---|
committer | paulg@google.com <paulg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-13 02:48:59 +0000 |
commit | cdaa86594dcdd5fc4ccac5dbf63a5e4dbfcdb8ea (patch) | |
tree | c9e3f5a89a3d9733ea75b97153ef2be4e8425aa3 /chrome/browser/views | |
parent | 431838df78d6e3cd06794a45cf0243be32149c7c (diff) | |
download | chromium_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.cc | 2 | ||||
-rw-r--r-- | chrome/browser/views/download_item_view.cc | 2 | ||||
-rw-r--r-- | chrome/browser/views/download_item_view.h | 2 | ||||
-rw-r--r-- | chrome/browser/views/download_shelf_view.cc | 6 | ||||
-rw-r--r-- | chrome/browser/views/download_tab_view.cc | 1181 | ||||
-rw-r--r-- | chrome/browser/views/download_tab_view.h | 252 | ||||
-rw-r--r-- | chrome/browser/views/options/advanced_contents_view.cc | 2 |
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" |