| Index: chrome/browser/ui/views/download/download_item_view.cc
|
| diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc
|
| index 18f9ef578de912190b730dc62e186c7c29755cbc..ac1d30aaf8cdf16566197f89a4dceea38e522612 100644
|
| --- a/chrome/browser/ui/views/download/download_item_view.cc
|
| +++ b/chrome/browser/ui/views/download/download_item_view.cc
|
| @@ -15,6 +15,8 @@
|
| #include "base/i18n/break_iterator.h"
|
| #include "base/i18n/rtl.h"
|
| #include "base/location.h"
|
| +#include "base/macros.h"
|
| +#include "base/memory/ptr_util.h"
|
| #include "base/metrics/histogram_macros.h"
|
| #include "base/single_thread_task_runner.h"
|
| #include "base/strings/string_util.h"
|
| @@ -39,23 +41,31 @@
|
| #include "chrome/browser/ui/views/frame/browser_view.h"
|
| #include "chrome/common/pref_names.h"
|
| #include "chrome/grit/generated_resources.h"
|
| -#include "chrome/grit/theme_resources.h"
|
| #include "components/prefs/pref_service.h"
|
| #include "content/public/browser/download_danger_type.h"
|
| #include "third_party/icu/source/common/unicode/uchar.h"
|
| #include "ui/accessibility/ax_view_state.h"
|
| #include "ui/base/l10n/l10n_util.h"
|
| +#include "ui/base/material_design/material_design_controller.h"
|
| #include "ui/base/resource/resource_bundle.h"
|
| #include "ui/base/theme_provider.h"
|
| #include "ui/events/event.h"
|
| #include "ui/gfx/animation/slide_animation.h"
|
| #include "ui/gfx/canvas.h"
|
| +#include "ui/gfx/color_palette.h"
|
| #include "ui/gfx/color_utils.h"
|
| #include "ui/gfx/image/image.h"
|
| -#include "ui/gfx/scoped_canvas.h"
|
| +#include "ui/gfx/paint_vector_icon.h"
|
| #include "ui/gfx/text_elider.h"
|
| #include "ui/gfx/text_utils.h"
|
| -#include "ui/views/controls/button/label_button.h"
|
| +#include "ui/gfx/vector_icons_public.h"
|
| +#include "ui/views/animation/flood_fill_ink_drop_ripple.h"
|
| +#include "ui/views/animation/ink_drop_highlight.h"
|
| +#include "ui/views/border.h"
|
| +#include "ui/views/controls/button/image_button.h"
|
| +#include "ui/views/controls/button/md_text_button.h"
|
| +#include "ui/views/controls/button/vector_icon_button.h"
|
| +#include "ui/views/controls/focusable_border.h"
|
| #include "ui/views/controls/label.h"
|
| #include "ui/views/mouse_constants.h"
|
| #include "ui/views/widget/root_view.h"
|
| @@ -66,30 +76,45 @@ using extensions::ExperienceSamplingEvent;
|
|
|
| namespace {
|
|
|
| -// TODO(paulg): These may need to be adjusted when download progress
|
| -// animation is added, and also possibly to take into account
|
| -// different screen resolutions.
|
| -const int kTextWidth = 140; // Pixels
|
| -const int kDangerousTextWidth = 200; // Pixels
|
| -const int kVerticalPadding = 3; // Pixels
|
| -const int kVerticalTextPadding = 2; // Pixels
|
| -const int kTooltipMaxWidth = 800; // Pixels
|
| +// All values in dp.
|
| +const int kTextWidth = 140;
|
| +const int kDangerousTextWidth = 200;
|
|
|
| -// Padding around progress indicator, on all sides.
|
| -const int kProgressPadding = 7;
|
| +// The normal height of the item which may be exceeded if text is large.
|
| +const int kDefaultHeight = 48;
|
|
|
| -// We add some padding before the left image so that the progress animation icon
|
| -// hides the corners of the left image.
|
| -const int kLeftPadding = 0; // Pixels.
|
| +// The vertical distance between the item's visual upper bound (as delineated by
|
| +// the separator on the right) and the edge of the shelf.
|
| +const int kTopBottomPadding = 6;
|
| +
|
| +// The minimum vertical padding above and below contents of the download item.
|
| +// This is only used when the text size is large.
|
| +const int kMinimumVerticalPadding = 2 + kTopBottomPadding;
|
| +
|
| +// Vertical padding between filename and status text.
|
| +const int kVerticalTextPadding = 1;
|
| +
|
| +const int kTooltipMaxWidth = 800;
|
| +
|
| +// Padding before the icon and at end of the item.
|
| +const int kStartPadding = 12;
|
| +const int kEndPadding = 6;
|
| +
|
| +// Horizontal padding between progress indicator and filename/status text.
|
| +const int kProgressTextPadding = 8;
|
|
|
| // The space between the Save and Discard buttons when prompting for a dangerous
|
| // download.
|
| -const int kButtonPadding = 5; // Pixels.
|
| +const int kButtonPadding = 5;
|
| +
|
| +// The touchable space around the dropdown button's icon.
|
| +const int kDropdownBorderWidth = 10;
|
|
|
| -// The space on the left and right side of the dangerous download label.
|
| -const int kLabelPadding = 4; // Pixels.
|
| +// The space on the right side of the dangerous download label.
|
| +const int kLabelPadding = 8;
|
|
|
| -const SkColor kFileNameDisabledColor = SkColorSetRGB(171, 192, 212);
|
| +// Height/width of the warning icon, also in dp.
|
| +const int kWarningIconSize = 24;
|
|
|
| // How long the 'download complete' animation should last for.
|
| const int kCompleteAnimationDurationMs = 2500;
|
| @@ -101,129 +126,96 @@ const int kInterruptedAnimationDurationMs = 2500;
|
| // downloaded item.
|
| const int kDisabledOnOpenDuration = 3000;
|
|
|
| +// The separator is drawn as a border. It's one dp wide.
|
| +class SeparatorBorder : public views::FocusableBorder {
|
| + public:
|
| + explicit SeparatorBorder(SkColor color) : color_(color) {}
|
| + ~SeparatorBorder() override {}
|
| +
|
| + void Paint(const views::View& view, gfx::Canvas* canvas) override {
|
| + if (view.HasFocus())
|
| + return FocusableBorder::Paint(view, canvas);
|
| +
|
| + int end_x = base::i18n::IsRTL() ? 0 : view.width() - 1;
|
| + canvas->DrawLine(gfx::Point(end_x, kTopBottomPadding),
|
| + gfx::Point(end_x, view.height() - kTopBottomPadding),
|
| + color_);
|
| + }
|
| +
|
| + gfx::Insets GetInsets() const override { return gfx::Insets(0, 0, 0, 1); }
|
| +
|
| + gfx::Size GetMinimumSize() const override {
|
| + return gfx::Size(1, 2 * kTopBottomPadding + 1);
|
| + }
|
| +
|
| + private:
|
| + SkColor color_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SeparatorBorder);
|
| +};
|
| +
|
| } // namespace
|
|
|
| +// Allows the DownloadItemView to control the InkDrop on the drop down button.
|
| +class DownloadItemView::DropDownButton : public views::VectorIconButton {
|
| + public:
|
| + explicit DropDownButton(views::VectorIconButtonDelegate* delegate)
|
| + : views::VectorIconButton(delegate) {}
|
| + ~DropDownButton() override {}
|
| +
|
| + // Promoted visibility to public.
|
| + void AnimateInkDrop(views::InkDropState state) {
|
| + // TODO(bruthig): Plumb in the proper Event.
|
| + views::VectorIconButton::AnimateInkDrop(state, nullptr /* event */);
|
| + }
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(DropDownButton);
|
| +};
|
| +
|
| DownloadItemView::DownloadItemView(DownloadItem* download_item,
|
| - DownloadShelfView* parent)
|
| - : warning_icon_(NULL),
|
| - shelf_(parent),
|
| - status_text_(l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING)),
|
| - body_state_(NORMAL),
|
| - drop_down_state_(NORMAL),
|
| - mode_(NORMAL_MODE),
|
| - drop_down_pressed_(false),
|
| - dragging_(false),
|
| - starting_drag_(false),
|
| - model_(download_item),
|
| - save_button_(NULL),
|
| - discard_button_(NULL),
|
| - dangerous_download_label_(NULL),
|
| - dangerous_download_label_sized_(false),
|
| - disabled_while_opening_(false),
|
| - creation_time_(base::Time::Now()),
|
| - time_download_warning_shown_(base::Time()),
|
| - weak_ptr_factory_(this) {
|
| + DownloadShelfView* parent)
|
| + : shelf_(parent),
|
| + status_text_(l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING)),
|
| + dropdown_state_(NORMAL),
|
| + mode_(NORMAL_MODE),
|
| + dragging_(false),
|
| + starting_drag_(false),
|
| + model_(download_item),
|
| + save_button_(nullptr),
|
| + discard_button_(nullptr),
|
| + dropdown_button_(new DropDownButton(this)),
|
| + dangerous_download_label_(nullptr),
|
| + dangerous_download_label_sized_(false),
|
| + disabled_while_opening_(false),
|
| + creation_time_(base::Time::Now()),
|
| + time_download_warning_shown_(base::Time()),
|
| + weak_ptr_factory_(this) {
|
| + SetInkDropMode(InkDropMode::ON);
|
| DCHECK(download());
|
| + DCHECK(ui::MaterialDesignController::IsModeMaterial());
|
| download()->AddObserver(this);
|
| set_context_menu_controller(this);
|
|
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| -
|
| - BodyImageSet normal_body_image_set = {
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_TOP),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM)
|
| - };
|
| - normal_body_image_set_ = normal_body_image_set;
|
| -
|
| - DropDownImageSet normal_drop_down_image_set = {
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_TOP),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_MIDDLE),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_BOTTOM)
|
| - };
|
| - normal_drop_down_image_set_ = normal_drop_down_image_set;
|
| -
|
| - BodyImageSet hot_body_image_set = {
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP_H),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE_H),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM_H),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP_H),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE_H),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM_H),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_TOP_H),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_H),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_H)
|
| - };
|
| - hot_body_image_set_ = hot_body_image_set;
|
| -
|
| - DropDownImageSet hot_drop_down_image_set = {
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_TOP_H),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_MIDDLE_H),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_BOTTOM_H)
|
| - };
|
| - hot_drop_down_image_set_ = hot_drop_down_image_set;
|
| -
|
| - BodyImageSet pushed_body_image_set = {
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP_P),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE_P),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM_P),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP_P),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE_P),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM_P),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_TOP_P),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_P),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_P)
|
| - };
|
| - pushed_body_image_set_ = pushed_body_image_set;
|
| -
|
| - DropDownImageSet pushed_drop_down_image_set = {
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_TOP_P),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_MIDDLE_P),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_MENU_BOTTOM_P)
|
| - };
|
| - pushed_drop_down_image_set_ = pushed_drop_down_image_set;
|
| -
|
| - BodyImageSet dangerous_mode_body_image_set = {
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_TOP_NO_DD),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_NO_DD),
|
| - rb.GetImageSkiaNamed(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_NO_DD)
|
| - };
|
| - dangerous_mode_body_image_set_ = dangerous_mode_body_image_set;
|
| -
|
| - malicious_mode_body_image_set_ = normal_body_image_set;
|
| + dropdown_button_->SetBorder(
|
| + views::Border::CreateEmptyBorder(gfx::Insets(kDropdownBorderWidth)));
|
| + dropdown_button_->set_ink_drop_size(gfx::Size(32, 32));
|
| + AddChildView(dropdown_button_);
|
|
|
| LoadIcon();
|
|
|
| - font_list_ = rb.GetFontList(ui::ResourceBundle::BaseFont);
|
| - box_height_ = std::max<int>(2 * kVerticalPadding + font_list_.GetHeight() +
|
| - kVerticalTextPadding + font_list_.GetHeight(),
|
| - 2 * kVerticalPadding +
|
| - normal_body_image_set_.top_left->height() +
|
| - normal_body_image_set_.bottom_left->height());
|
| -
|
| - box_y_ = std::max(0, (2 * kProgressPadding +
|
| - DownloadShelf::kProgressIndicatorSize - box_height_) /
|
| - 2);
|
| -
|
| - body_hover_animation_.reset(new gfx::SlideAnimation(this));
|
| - drop_hover_animation_.reset(new gfx::SlideAnimation(this));
|
| + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| + font_list_ =
|
| + rb.GetFontList(ui::ResourceBundle::BaseFont).DeriveWithSizeDelta(1);
|
| + status_font_list_ =
|
| + rb.GetFontList(ui::ResourceBundle::BaseFont).DeriveWithSizeDelta(-2);
|
|
|
| SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
|
|
|
| OnDownloadUpdated(download());
|
| - UpdateDropDownButtonPosition();
|
| +
|
| + SetDropdownState(NORMAL);
|
| + UpdateColorsFromTheme();
|
| }
|
|
|
| DownloadItemView::~DownloadItemView() {
|
| @@ -257,6 +249,13 @@ void DownloadItemView::StopDownloadProgress() {
|
| progress_timer_.Stop();
|
| }
|
|
|
| +// static
|
| +SkColor DownloadItemView::GetTextColorForThemeProvider(
|
| + const ui::ThemeProvider* theme) {
|
| + return theme ? theme->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT)
|
| + : gfx::kPlaceholderColor;
|
| +}
|
| +
|
| void DownloadItemView::OnExtractIconComplete(gfx::Image* icon_bitmap) {
|
| if (icon_bitmap)
|
| shelf_->SchedulePaint();
|
| @@ -345,69 +344,62 @@ void DownloadItemView::OnDownloadOpened(DownloadItem* download) {
|
|
|
| // In dangerous mode we have to layout our buttons.
|
| void DownloadItemView::Layout() {
|
| + UpdateColorsFromTheme();
|
| +
|
| if (IsShowingWarningDialog()) {
|
| - BodyImageSet* body_image_set =
|
| - (mode_ == DANGEROUS_MODE) ? &dangerous_mode_body_image_set_ :
|
| - &malicious_mode_body_image_set_;
|
| - int x = kLeftPadding + body_image_set->top_left->width() +
|
| - warning_icon_->width() + kLabelPadding;
|
| - int y = (height() - dangerous_download_label_->height()) / 2;
|
| - dangerous_download_label_->SetBounds(x, y,
|
| - dangerous_download_label_->width(),
|
| - dangerous_download_label_->height());
|
| + gfx::Point child_origin(
|
| + kStartPadding + kWarningIconSize + kStartPadding,
|
| + (height() - dangerous_download_label_->height()) / 2);
|
| + dangerous_download_label_->SetPosition(child_origin);
|
| +
|
| + child_origin.Offset(dangerous_download_label_->width() + kLabelPadding, 0);
|
| gfx::Size button_size = GetButtonSize();
|
| - x += dangerous_download_label_->width() + kLabelPadding;
|
| - y = (height() - button_size.height()) / 2;
|
| + child_origin.set_y((height() - button_size.height()) / 2);
|
| if (save_button_) {
|
| - save_button_->SetBounds(x, y, button_size.width(), button_size.height());
|
| - x += button_size.width() + kButtonPadding;
|
| + save_button_->SetBoundsRect(gfx::Rect(child_origin, button_size));
|
| + child_origin.Offset(button_size.width() + kButtonPadding, 0);
|
| }
|
| - discard_button_->SetBounds(x, y, button_size.width(), button_size.height());
|
| - UpdateColorsFromTheme();
|
| + discard_button_->SetBoundsRect(gfx::Rect(child_origin, button_size));
|
| + }
|
| +
|
| + if (mode_ != DANGEROUS_MODE) {
|
| + dropdown_button_->SizeToPreferredSize();
|
| + dropdown_button_->SetPosition(
|
| + gfx::Point(width() - dropdown_button_->width() - kEndPadding,
|
| + (height() - dropdown_button_->height()) / 2));
|
| }
|
| }
|
|
|
| gfx::Size DownloadItemView::GetPreferredSize() const {
|
| - int width, height;
|
| -
|
| - // First, we set the height to the height of two rows or text plus margins.
|
| - height = 2 * kVerticalPadding + 2 * font_list_.GetHeight() +
|
| - kVerticalTextPadding;
|
| - // Then we increase the size if the progress icon doesn't fit.
|
| - height = std::max<int>(
|
| - height, DownloadShelf::kProgressIndicatorSize + 2 * kProgressPadding);
|
| + int width = 0;
|
| + // We set the height to the height of two rows or text plus margins.
|
| + int child_height = font_list_.GetBaseline() + kVerticalTextPadding +
|
| + status_font_list_.GetHeight();
|
|
|
| if (IsShowingWarningDialog()) {
|
| - const BodyImageSet* body_image_set =
|
| - (mode_ == DANGEROUS_MODE) ? &dangerous_mode_body_image_set_ :
|
| - &malicious_mode_body_image_set_;
|
| - width = kLeftPadding + body_image_set->top_left->width();
|
| - width += warning_icon_->width() + kLabelPadding;
|
| - width += dangerous_download_label_->width() + kLabelPadding;
|
| + // Width.
|
| + width = kStartPadding + kWarningIconSize + kStartPadding +
|
| + dangerous_download_label_->width() + kLabelPadding;
|
| gfx::Size button_size = GetButtonSize();
|
| - // Make sure the button fits.
|
| - height = std::max<int>(height, 2 * kVerticalPadding + button_size.height());
|
| - // Then we make sure the warning icon fits.
|
| - height = std::max<int>(height, 2 * kVerticalPadding +
|
| - warning_icon_->height());
|
| if (save_button_)
|
| width += button_size.width() + kButtonPadding;
|
| - width += button_size.width();
|
| - width += body_image_set->top_right->width();
|
| - if (mode_ == MALICIOUS_MODE)
|
| - width += normal_drop_down_image_set_.top->width();
|
| + width += button_size.width() + kEndPadding;
|
| +
|
| + // Height: make sure the button fits and the warning icon fits.
|
| + child_height =
|
| + std::max({child_height, button_size.height(), kWarningIconSize});
|
| } else {
|
| - width = kLeftPadding + normal_body_image_set_.top_left->width();
|
| - width += DownloadShelf::kProgressIndicatorSize + 2 * kProgressPadding;
|
| - width += kTextWidth;
|
| - width += normal_body_image_set_.top_right->width();
|
| - width += normal_drop_down_image_set_.top->width();
|
| + width = kStartPadding + DownloadShelf::kProgressIndicatorSize +
|
| + kProgressTextPadding + kTextWidth + kEndPadding;
|
| }
|
| - return gfx::Size(width, height);
|
| +
|
| + if (mode_ != DANGEROUS_MODE)
|
| + width += dropdown_button_->GetPreferredSize().width();
|
| +
|
| + return gfx::Size(width, std::max(kDefaultHeight,
|
| + 2 * kMinimumVerticalPadding + child_height));
|
| }
|
|
|
| -// Handle a mouse click and open the context menu if the mouse is
|
| -// over the drop-down region.
|
| bool DownloadItemView::OnMousePressed(const ui::MouseEvent& event) {
|
| HandlePressEvent(event, event.IsOnlyLeftMouseButton());
|
| return true;
|
| @@ -422,6 +414,7 @@ bool DownloadItemView::OnMouseDragged(const ui::MouseEvent& event) {
|
| if (!starting_drag_) {
|
| starting_drag_ = true;
|
| drag_start_point_ = event.location();
|
| + AnimateInkDrop(views::InkDropState::HIDDEN, &event);
|
| }
|
| if (dragging_) {
|
| if (download()->GetState() == DownloadItem::COMPLETE) {
|
| @@ -429,8 +422,8 @@ bool DownloadItemView::OnMouseDragged(const ui::MouseEvent& event) {
|
| gfx::Image* icon = im->LookupIconFromFilepath(
|
| download()->GetTargetFilePath(), IconLoader::SMALL);
|
| views::Widget* widget = GetWidget();
|
| - DragDownloadItem(
|
| - download(), icon, widget ? widget->GetNativeView() : NULL);
|
| + DragDownloadItem(download(), icon,
|
| + widget ? widget->GetNativeView() : NULL);
|
| }
|
| } else if (ExceededDragThreshold(event.location() - drag_start_point_)) {
|
| dragging_ = true;
|
| @@ -444,7 +437,7 @@ void DownloadItemView::OnMouseReleased(const ui::MouseEvent& event) {
|
|
|
| void DownloadItemView::OnMouseCaptureLost() {
|
| // Mouse should not activate us in dangerous mode.
|
| - if (mode_ == DANGEROUS_MODE)
|
| + if (mode_ != NORMAL_MODE)
|
| return;
|
|
|
| if (dragging_) {
|
| @@ -452,24 +445,6 @@ void DownloadItemView::OnMouseCaptureLost() {
|
| dragging_ = false;
|
| starting_drag_ = false;
|
| }
|
| - SetState(NORMAL, NORMAL);
|
| -}
|
| -
|
| -void DownloadItemView::OnMouseMoved(const ui::MouseEvent& event) {
|
| - // Mouse should not activate us in dangerous mode.
|
| - if (mode_ == DANGEROUS_MODE)
|
| - return;
|
| -
|
| - bool on_body = !InDropDownButtonXCoordinateRange(event.x());
|
| - SetState(on_body ? HOT : NORMAL, on_body ? NORMAL : HOT);
|
| -}
|
| -
|
| -void DownloadItemView::OnMouseExited(const ui::MouseEvent& event) {
|
| - // Mouse should not activate us in dangerous mode.
|
| - if (mode_ == DANGEROUS_MODE)
|
| - return;
|
| -
|
| - SetState(NORMAL, drop_down_pressed_ ? PUSHED : NORMAL);
|
| }
|
|
|
| bool DownloadItemView::OnKeyPressed(const ui::KeyEvent& event) {
|
| @@ -479,6 +454,7 @@ bool DownloadItemView::OnKeyPressed(const ui::KeyEvent& event) {
|
|
|
| if (event.key_code() == ui::VKEY_SPACE ||
|
| event.key_code() == ui::VKEY_RETURN) {
|
| + AnimateInkDrop(views::InkDropState::ACTION_TRIGGERED, nullptr /* &event */);
|
| // OpenDownload may delete this, so don't add any code after this line.
|
| OpenDownload();
|
| return true;
|
| @@ -509,6 +485,34 @@ void DownloadItemView::GetAccessibleState(ui::AXViewState* state) {
|
|
|
| void DownloadItemView::OnThemeChanged() {
|
| UpdateColorsFromTheme();
|
| + SchedulePaint();
|
| +}
|
| +
|
| +void DownloadItemView::AddInkDropLayer(ui::Layer* ink_drop_layer) {
|
| + InkDropHostView::AddInkDropLayer(ink_drop_layer);
|
| + // The layer that's added to host the ink drop layer must mask to bounds
|
| + // so the hover effect is clipped while animating open.
|
| + layer()->SetMasksToBounds(true);
|
| +}
|
| +
|
| +std::unique_ptr<views::InkDropRipple> DownloadItemView::CreateInkDropRipple()
|
| + const {
|
| + return base::MakeUnique<views::FloodFillInkDropRipple>(
|
| + GetLocalBounds(), GetInkDropCenterBasedOnLastEvent(),
|
| + color_utils::DeriveDefaultIconColor(GetTextColor()),
|
| + ink_drop_visible_opacity());
|
| +}
|
| +
|
| +std::unique_ptr<views::InkDropHighlight>
|
| +DownloadItemView::CreateInkDropHighlight() const {
|
| + if (IsShowingWarningDialog())
|
| + return nullptr;
|
| +
|
| + gfx::Size size = GetPreferredSize();
|
| + return base::MakeUnique<views::InkDropHighlight>(
|
| + size, kInkDropSmallCornerRadius,
|
| + gfx::RectF(gfx::SizeF(size)).CenterPoint(),
|
| + color_utils::DeriveDefaultIconColor(GetTextColor()));
|
| }
|
|
|
| void DownloadItemView::OnGestureEvent(ui::GestureEvent* event) {
|
| @@ -524,21 +528,32 @@ void DownloadItemView::OnGestureEvent(ui::GestureEvent* event) {
|
| return;
|
| }
|
|
|
| - SetState(NORMAL, NORMAL);
|
| views::View::OnGestureEvent(event);
|
| }
|
|
|
| void DownloadItemView::ShowContextMenuForView(View* source,
|
| const gfx::Point& point,
|
| ui::MenuSourceType source_type) {
|
| - // |point| is in screen coordinates. So convert it to local coordinates first.
|
| - gfx::Point local_point = point;
|
| - ConvertPointFromScreen(this, &local_point);
|
| - ShowContextMenuImpl(local_point, source_type);
|
| + ShowContextMenuImpl(gfx::Rect(point, gfx::Size()), source_type);
|
| }
|
|
|
| void DownloadItemView::ButtonPressed(views::Button* sender,
|
| const ui::Event& event) {
|
| + if (sender == dropdown_button_) {
|
| + // TODO(estade): this is copied from ToolbarActionView but should be shared
|
| + // one way or another.
|
| + ui::MenuSourceType type = ui::MENU_SOURCE_NONE;
|
| + if (event.IsMouseEvent())
|
| + type = ui::MENU_SOURCE_MOUSE;
|
| + else if (event.IsKeyEvent())
|
| + type = ui::MENU_SOURCE_KEYBOARD;
|
| + else if (event.IsGestureEvent())
|
| + type = ui::MENU_SOURCE_TOUCH;
|
| + SetDropdownState(PUSHED);
|
| + ShowContextMenuImpl(dropdown_button_->GetBoundsInScreen(), type);
|
| + return;
|
| + }
|
| +
|
| base::TimeDelta warning_duration;
|
| if (!time_download_warning_shown_.is_null())
|
| warning_duration = base::Time::Now() - time_download_warning_shown_;
|
| @@ -564,25 +579,27 @@ void DownloadItemView::ButtonPressed(views::Button* sender,
|
| if (!model_.IsMalicious() && model_.ShouldAllowDownloadFeedback() &&
|
| !shelf_->browser()->profile()->IsOffTheRecord()) {
|
| if (!shelf_->browser()->profile()->GetPrefs()->HasPrefPath(
|
| - prefs::kSafeBrowsingExtendedReportingEnabled)) {
|
| + prefs::kSafeBrowsingExtendedReportingEnabled)) {
|
| // Show dialog, because the dialog hasn't been shown before.
|
| DownloadFeedbackDialogView::Show(
|
| - shelf_->get_parent()->GetNativeWindow(),
|
| - shelf_->browser()->profile(),
|
| + shelf_->get_parent()->GetNativeWindow(), shelf_->browser()->profile(),
|
| shelf_->GetNavigator(),
|
| - base::Bind(
|
| - &DownloadItemView::PossiblySubmitDownloadToFeedbackService,
|
| - weak_ptr_factory_.GetWeakPtr()));
|
| + base::Bind(&DownloadItemView::PossiblySubmitDownloadToFeedbackService,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| } else {
|
| PossiblySubmitDownloadToFeedbackService(
|
| shelf_->browser()->profile()->GetPrefs()->GetBoolean(
|
| - prefs::kSafeBrowsingExtendedReportingEnabled));
|
| + prefs::kSafeBrowsingExtendedReportingEnabled));
|
| }
|
| return;
|
| }
|
| download()->Remove();
|
| }
|
|
|
| +SkColor DownloadItemView::GetVectorIconBaseColor() const {
|
| + return GetTextColor();
|
| +}
|
| +
|
| void DownloadItemView::AnimationProgressed(const gfx::Animation* animation) {
|
| // We don't care if what animation (body button/drop button/complete),
|
| // is calling back, as they all have to go through the same paint call.
|
| @@ -590,299 +607,129 @@ void DownloadItemView::AnimationProgressed(const gfx::Animation* animation) {
|
| }
|
|
|
| void DownloadItemView::OnPaint(gfx::Canvas* canvas) {
|
| - OnPaintBackground(canvas);
|
| - if (HasFocus())
|
| - canvas->DrawFocusRect(GetLocalBounds());
|
| + // Make sure to draw |this| opaquely. Since the toolbar color can be partially
|
| + // transparent, start with a black backdrop (which is the default initialized
|
| + // color for opaque canvases).
|
| + canvas->DrawColor(SK_ColorBLACK);
|
| + canvas->DrawColor(
|
| + GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR));
|
| +
|
| + DrawStatusText(canvas);
|
| + DrawFilename(canvas);
|
| + DrawIcon(canvas);
|
| + OnPaintBorder(canvas);
|
| }
|
|
|
| -// The DownloadItemView can be in three major modes (NORMAL_MODE, DANGEROUS_MODE
|
| -// and MALICIOUS_MODE).
|
| -//
|
| -// NORMAL_MODE: We are displaying an in-progress or completed download.
|
| -// .-------------------------------+-.
|
| -// | [icon] Filename |v|
|
| -// | [ ] Status | |
|
| -// `-------------------------------+-'
|
| -// | | \_ Drop down button. Invokes menu. Responds
|
| -// | | to mouse. (NORMAL, HOT or PUSHED).
|
| -// | \_ Icon is overlaid on top of in-progress animation.
|
| -// \_ Both the body and the drop down button respond to mouse hover and can be
|
| -// pushed (NORMAL, HOT or PUSHED).
|
| -//
|
| -// DANGEROUS_MODE: The file could be potentially dangerous.
|
| -// .-------------------------------------------------------.
|
| -// | [ ! ] [This type of file can ] [ Keep ] [ Discard ] |
|
| -// | [ ] [destroy your computer..] [ ] [ ] |
|
| -// `-------------------------------------------------------'
|
| -// | | | | \_ No drop down button.
|
| -// | | | \_ Buttons are views::LabelButtons.
|
| -// | | \_ Text is in a label (dangerous_download_label_)
|
| -// | \_ Warning icon. No progress animation.
|
| -// \_ Body is static. Doesn't respond to mouse hover or press. (NORMAL only)
|
| -//
|
| -// MALICIOUS_MODE: The file is known malware.
|
| -// .---------------------------------------------+-.
|
| -// | [ - ] [This file is malicious.] [ Discard ] |v|
|
| -// | [ ] [ ] [ ] | |-.
|
| -// `---------------------------------------------+-' |
|
| -// | | | | Drop down button. Responds to
|
| -// | | | | mouse.(NORMAL, HOT or PUSHED)
|
| -// | | | \_ Button is a views::LabelButton.
|
| -// | | \_ Text is in a label (dangerous_download_label_)
|
| -// | \_ Warning icon. No progress animation.
|
| -// \_ Body is static. Doesn't respond to mouse hover or press. (NORMAL only)
|
| -//
|
| -void DownloadItemView::OnPaintBackground(gfx::Canvas* canvas) {
|
| - BodyImageSet* body_image_set = NULL;
|
| - switch (mode_) {
|
| - case NORMAL_MODE:
|
| - if (body_state_ == PUSHED)
|
| - body_image_set = &pushed_body_image_set_;
|
| - else // NORMAL or HOT
|
| - body_image_set = &normal_body_image_set_;
|
| - break;
|
| - case DANGEROUS_MODE:
|
| - body_image_set = &dangerous_mode_body_image_set_;
|
| - break;
|
| - case MALICIOUS_MODE:
|
| - body_image_set = &malicious_mode_body_image_set_;
|
| - break;
|
| - default:
|
| - NOTREACHED();
|
| - }
|
| +int DownloadItemView::GetYForFilenameText() const {
|
| + int text_height = font_list_.GetBaseline();
|
| + if (!status_text_.empty())
|
| + text_height += kVerticalTextPadding + status_font_list_.GetBaseline();
|
| + return (height() - text_height) / 2;
|
| +}
|
|
|
| - DropDownImageSet* drop_down_image_set = NULL;
|
| - switch (mode_) {
|
| - case NORMAL_MODE:
|
| - case MALICIOUS_MODE:
|
| - if (drop_down_state_ == PUSHED)
|
| - drop_down_image_set = &pushed_drop_down_image_set_;
|
| - else // NORMAL or HOT
|
| - drop_down_image_set = &normal_drop_down_image_set_;
|
| - break;
|
| - case DANGEROUS_MODE:
|
| - // We don't use a drop down button for mode_ == DANGEROUS_MODE. So we let
|
| - // drop_down_image_set == NULL.
|
| - break;
|
| - default:
|
| - NOTREACHED();
|
| - }
|
| +void DownloadItemView::DrawStatusText(gfx::Canvas* canvas) {
|
| + if (status_text_.empty() || IsShowingWarningDialog())
|
| + return;
|
|
|
| - int center_width = width() - kLeftPadding -
|
| - body_image_set->left->width() -
|
| - body_image_set->right->width() -
|
| - (drop_down_image_set ?
|
| - normal_drop_down_image_set_.center->width() :
|
| - 0);
|
| + int mirrored_x = GetMirroredXWithWidthInView(
|
| + kStartPadding + DownloadShelf::kProgressIndicatorSize +
|
| + kProgressTextPadding,
|
| + kTextWidth);
|
| + int y =
|
| + GetYForFilenameText() + font_list_.GetBaseline() + kVerticalTextPadding;
|
| + canvas->DrawStringRect(
|
| + status_text_, status_font_list_, GetDimmedTextColor(),
|
| + gfx::Rect(mirrored_x, y, kTextWidth, status_font_list_.GetHeight()));
|
| +}
|
|
|
| - // May be caused by animation.
|
| - if (center_width <= 0)
|
| +void DownloadItemView::DrawFilename(gfx::Canvas* canvas) {
|
| + if (IsShowingWarningDialog())
|
| return;
|
|
|
| - // Draw status before button image to effectively lighten text. No status for
|
| - // warning dialogs.
|
| - if (!IsShowingWarningDialog()) {
|
| - if (!status_text_.empty()) {
|
| - int mirrored_x = GetMirroredXWithWidthInView(
|
| - 2 * kProgressPadding + DownloadShelf::kProgressIndicatorSize,
|
| - kTextWidth);
|
| - // Add font_list_.height() to compensate for title, which is drawn later.
|
| - int y = box_y_ + kVerticalPadding + font_list_.GetHeight() +
|
| - kVerticalTextPadding;
|
| - SkColor file_name_color = GetThemeProvider()->GetColor(
|
| - ThemeProperties::COLOR_BOOKMARK_TEXT);
|
| - // If text is light-on-dark, lightening it alone will do nothing. In this
|
| - // case we multiply color components by 80% before drawing.
|
| - if (!color_utils::IsDark(file_name_color)) {
|
| - file_name_color =
|
| - color_utils::AlphaBlend(SK_ColorBLACK, file_name_color, 255 / 5);
|
| - }
|
| - canvas->DrawStringRect(status_text_, font_list_, file_name_color,
|
| - gfx::Rect(mirrored_x, y, kTextWidth,
|
| - font_list_.GetHeight()));
|
| - }
|
| + // Print the text, left aligned and always print the file extension.
|
| + // Last value of x was the end of the right image, just before the button.
|
| + // Note that in dangerous mode we use a label (as the text is multi-line).
|
| + base::string16 filename;
|
| + if (!disabled_while_opening_) {
|
| + filename = gfx::ElideFilename(download()->GetFileNameToReportUser(),
|
| + font_list_, kTextWidth);
|
| + } else {
|
| + // First, Calculate the download status opening string width.
|
| + base::string16 status_string = l10n_util::GetStringFUTF16(
|
| + IDS_DOWNLOAD_STATUS_OPENING, base::string16());
|
| + int status_string_width = gfx::GetStringWidth(status_string, font_list_);
|
| + // Then, elide the file name.
|
| + base::string16 filename_string =
|
| + gfx::ElideFilename(download()->GetFileNameToReportUser(), font_list_,
|
| + kTextWidth - status_string_width);
|
| + // Last, concat the whole string.
|
| + filename = l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_OPENING,
|
| + filename_string);
|
| }
|
|
|
| - // Paint the background images.
|
| - {
|
| - gfx::ScopedRTLFlipCanvas scoped_canvas(canvas, width());
|
| -
|
| - int x = kLeftPadding;
|
| - PaintImages(canvas,
|
| - body_image_set->top_left, body_image_set->left,
|
| - body_image_set->bottom_left,
|
| - x, box_y_, box_height_, body_image_set->top_left->width());
|
| - x += body_image_set->top_left->width();
|
| - PaintImages(canvas,
|
| - body_image_set->top, body_image_set->center,
|
| - body_image_set->bottom,
|
| - x, box_y_, box_height_, center_width);
|
| - x += center_width;
|
| - PaintImages(canvas,
|
| - body_image_set->top_right, body_image_set->right,
|
| - body_image_set->bottom_right,
|
| - x, box_y_, box_height_, body_image_set->top_right->width());
|
| -
|
| - // Overlay our body hot state. Warning dialogs don't display body a hot
|
| - // state.
|
| - if (!IsShowingWarningDialog() &&
|
| - body_hover_animation_->GetCurrentValue() > 0) {
|
| - canvas->SaveLayerAlpha(
|
| - static_cast<int>(body_hover_animation_->GetCurrentValue() * 255));
|
| -
|
| - int x = kLeftPadding;
|
| - PaintImages(canvas,
|
| - hot_body_image_set_.top_left, hot_body_image_set_.left,
|
| - hot_body_image_set_.bottom_left,
|
| - x, box_y_, box_height_,
|
| - hot_body_image_set_.top_left->width());
|
| - x += body_image_set->top_left->width();
|
| - PaintImages(canvas,
|
| - hot_body_image_set_.top, hot_body_image_set_.center,
|
| - hot_body_image_set_.bottom,
|
| - x, box_y_, box_height_, center_width);
|
| - x += center_width;
|
| - PaintImages(canvas,
|
| - hot_body_image_set_.top_right, hot_body_image_set_.right,
|
| - hot_body_image_set_.bottom_right,
|
| - x, box_y_, box_height_,
|
| - hot_body_image_set_.top_right->width());
|
| - canvas->Restore();
|
| - }
|
| -
|
| - x += body_image_set->top_right->width();
|
| -
|
| - // Paint the drop-down.
|
| - if (drop_down_image_set) {
|
| - PaintImages(canvas,
|
| - drop_down_image_set->top, drop_down_image_set->center,
|
| - drop_down_image_set->bottom,
|
| - x, box_y_, box_height_, drop_down_image_set->top->width());
|
| -
|
| - // Overlay our drop-down hot state.
|
| - if (drop_hover_animation_->GetCurrentValue() > 0) {
|
| - canvas->SaveLayerAlpha(
|
| - static_cast<int>(drop_hover_animation_->GetCurrentValue() * 255));
|
| -
|
| - PaintImages(canvas,
|
| - drop_down_image_set->top, drop_down_image_set->center,
|
| - drop_down_image_set->bottom,
|
| - x, box_y_, box_height_, drop_down_image_set->top->width());
|
| + int mirrored_x = GetMirroredXWithWidthInView(
|
| + kStartPadding + DownloadShelf::kProgressIndicatorSize +
|
| + kProgressTextPadding,
|
| + kTextWidth);
|
| + canvas->DrawStringRect(filename, font_list_,
|
| + enabled() ? GetTextColor() : GetDimmedTextColor(),
|
| + gfx::Rect(mirrored_x, GetYForFilenameText(),
|
| + kTextWidth, font_list_.GetHeight()));
|
| +}
|
|
|
| - canvas->Restore();
|
| - }
|
| - }
|
| +void DownloadItemView::DrawIcon(gfx::Canvas* canvas) {
|
| + if (IsShowingWarningDialog()) {
|
| + int icon_x = base::i18n::IsRTL()
|
| + ? width() - kWarningIconSize - kStartPadding
|
| + : kStartPadding;
|
| + int icon_y = (height() - kWarningIconSize) / 2;
|
| + canvas->DrawImageInt(GetWarningIcon(), icon_x, icon_y);
|
| + return;
|
| }
|
|
|
| - // Print the text, left aligned and always print the file extension.
|
| - // Last value of x was the end of the right image, just before the button.
|
| - // Note that in dangerous mode we use a label (as the text is multi-line).
|
| - if (!IsShowingWarningDialog()) {
|
| - base::string16 filename;
|
| - if (!disabled_while_opening_) {
|
| - filename = gfx::ElideFilename(download()->GetFileNameToReportUser(),
|
| - font_list_, kTextWidth);
|
| + // Paint download progress.
|
| + DownloadItem::DownloadState state = download()->GetState();
|
| + canvas->Save();
|
| + int progress_x =
|
| + base::i18n::IsRTL()
|
| + ? width() - kStartPadding - DownloadShelf::kProgressIndicatorSize
|
| + : kStartPadding;
|
| + int progress_y = (height() - DownloadShelf::kProgressIndicatorSize) / 2;
|
| + canvas->Translate(gfx::Vector2d(progress_x, progress_y));
|
| +
|
| + if (state == DownloadItem::IN_PROGRESS) {
|
| + base::TimeDelta progress_time = previous_progress_elapsed_;
|
| + if (!download()->IsPaused())
|
| + progress_time += base::TimeTicks::Now() - progress_start_time_;
|
| + DownloadShelf::PaintDownloadProgress(
|
| + canvas, *GetThemeProvider(), progress_time, model_.PercentComplete());
|
| + } else if (complete_animation_.get() && complete_animation_->is_animating()) {
|
| + if (state == DownloadItem::INTERRUPTED) {
|
| + DownloadShelf::PaintDownloadInterrupted(
|
| + canvas, *GetThemeProvider(), complete_animation_->GetCurrentValue());
|
| } else {
|
| - // First, Calculate the download status opening string width.
|
| - base::string16 status_string =
|
| - l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_OPENING,
|
| - base::string16());
|
| - int status_string_width = gfx::GetStringWidth(status_string, font_list_);
|
| - // Then, elide the file name.
|
| - base::string16 filename_string =
|
| - gfx::ElideFilename(download()->GetFileNameToReportUser(), font_list_,
|
| - kTextWidth - status_string_width);
|
| - // Last, concat the whole string.
|
| - filename = l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_OPENING,
|
| - filename_string);
|
| + DCHECK_EQ(DownloadItem::COMPLETE, state);
|
| + DownloadShelf::PaintDownloadComplete(
|
| + canvas, *GetThemeProvider(), complete_animation_->GetCurrentValue());
|
| }
|
| -
|
| - int mirrored_x = GetMirroredXWithWidthInView(
|
| - 2 * kProgressPadding + DownloadShelf::kProgressIndicatorSize,
|
| - kTextWidth);
|
| - SkColor file_name_color = GetThemeProvider()->GetColor(
|
| - ThemeProperties::COLOR_BOOKMARK_TEXT);
|
| - int y =
|
| - box_y_ + (status_text_.empty() ?
|
| - ((box_height_ - font_list_.GetHeight()) / 2) : kVerticalPadding);
|
| -
|
| - // Draw the file's name.
|
| - canvas->DrawStringRect(
|
| - filename, font_list_,
|
| - enabled() ? file_name_color : kFileNameDisabledColor,
|
| - gfx::Rect(mirrored_x, y, kTextWidth, font_list_.GetHeight()));
|
| }
|
| + canvas->Restore();
|
|
|
| - // Load the icon.
|
| + // Fetch the already-loaded icon.
|
| IconManager* im = g_browser_process->icon_manager();
|
| - gfx::Image* image = im->LookupIconFromFilepath(
|
| - download()->GetTargetFilePath(), IconLoader::SMALL);
|
| - const gfx::ImageSkia* icon = NULL;
|
| - if (IsShowingWarningDialog())
|
| - icon = warning_icon_;
|
| - else if (image)
|
| - icon = image->ToImageSkia();
|
| -
|
| - // We count on the fact that the icon manager will cache the icons and if one
|
| - // is available, it will be cached here. We *don't* want to request the icon
|
| - // to be loaded here, since this will also get called if the icon can't be
|
| - // loaded, in which case LookupIcon will always be NULL. The loading will be
|
| - // triggered only when we think the status might change.
|
| - if (icon) {
|
| - int progress_x =
|
| - base::i18n::IsRTL()
|
| - ? width() - kProgressPadding - DownloadShelf::kProgressIndicatorSize
|
| - : kProgressPadding;
|
| - int progress_y = kProgressPadding;
|
| -
|
| - if (!IsShowingWarningDialog()) {
|
| - canvas->Save();
|
| - canvas->Translate(gfx::Vector2d(progress_x, progress_y));
|
| -
|
| - DownloadItem::DownloadState state = download()->GetState();
|
| - if (state == DownloadItem::IN_PROGRESS) {
|
| - base::TimeDelta progress_time = previous_progress_elapsed_;
|
| - if (!download()->IsPaused())
|
| - progress_time += base::TimeTicks::Now() - progress_start_time_;
|
| - DownloadShelf::PaintDownloadProgress(canvas, *GetThemeProvider(),
|
| - progress_time,
|
| - model_.PercentComplete());
|
| - } else if (complete_animation_.get() &&
|
| - complete_animation_->is_animating()) {
|
| - if (state == DownloadItem::INTERRUPTED) {
|
| - DownloadShelf::PaintDownloadInterrupted(
|
| - canvas, *GetThemeProvider(),
|
| - complete_animation_->GetCurrentValue());
|
| - } else {
|
| - DCHECK_EQ(DownloadItem::COMPLETE, state);
|
| - DownloadShelf::PaintDownloadComplete(
|
| - canvas, *GetThemeProvider(),
|
| - complete_animation_->GetCurrentValue());
|
| - }
|
| - }
|
| - canvas->Restore();
|
| - }
|
| -
|
| - // Draw the icon image.
|
| - int icon_x, icon_y;
|
| + gfx::Image* icon = im->LookupIconFromFilepath(download()->GetTargetFilePath(),
|
| + IconLoader::SMALL);
|
| + if (!icon)
|
| + return;
|
|
|
| - if (IsShowingWarningDialog()) {
|
| - icon_x = kLeftPadding + body_image_set->top_left->width();
|
| - icon_x = GetMirroredXWithWidthInView(icon_x, icon->width());
|
| - icon_y = (height() - icon->height()) / 2;
|
| - } else {
|
| - icon_x = progress_x + DownloadShelf::kFiletypeIconOffset;
|
| - icon_y = progress_y + DownloadShelf::kFiletypeIconOffset;
|
| - }
|
| - if (enabled()) {
|
| - canvas->DrawImageInt(*icon, icon_x, icon_y);
|
| - } else {
|
| - // Use an alpha to make the image look disabled.
|
| - SkPaint paint;
|
| - paint.setAlpha(120);
|
| - canvas->DrawImageInt(*icon, icon_x, icon_y, paint);
|
| - }
|
| - }
|
| + // Draw the icon image.
|
| + int icon_x = progress_x + DownloadShelf::kFiletypeIconOffset;
|
| + int icon_y = progress_y + DownloadShelf::kFiletypeIconOffset;
|
| + SkPaint paint;
|
| + // Use an alpha to make the image look disabled.
|
| + if (!enabled())
|
| + paint.setAlpha(120);
|
| + canvas->DrawImageInt(*icon->ToImageSkia(), icon_x, icon_y, paint);
|
| }
|
|
|
| void DownloadItemView::OnFocus() {
|
| @@ -940,8 +787,7 @@ void DownloadItemView::PossiblySubmitDownloadToFeedbackService(bool enabled) {
|
| void DownloadItemView::LoadIcon() {
|
| IconManager* im = g_browser_process->icon_manager();
|
| last_download_item_path_ = download()->GetTargetFilePath();
|
| - im->LoadIcon(last_download_item_path_,
|
| - IconLoader::SMALL,
|
| + im->LoadIcon(last_download_item_path_, IconLoader::SMALL,
|
| base::Bind(&DownloadItemView::OnExtractIconComplete,
|
| base::Unretained(this)),
|
| &cancelable_task_tracker_);
|
| @@ -956,17 +802,23 @@ void DownloadItemView::LoadIconIfItemPathChanged() {
|
| }
|
|
|
| void DownloadItemView::UpdateColorsFromTheme() {
|
| - if (dangerous_download_label_ && GetThemeProvider()) {
|
| - dangerous_download_label_->SetEnabledColor(
|
| - GetThemeProvider()->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT));
|
| - }
|
| + if (!GetThemeProvider())
|
| + return;
|
| +
|
| + SetBorder(base::MakeUnique<SeparatorBorder>(GetThemeProvider()->GetColor(
|
| + ThemeProperties::COLOR_TOOLBAR_VERTICAL_SEPARATOR)));
|
| +
|
| + SkColor text_color = GetTextColor();
|
| + if (dangerous_download_label_)
|
| + dangerous_download_label_->SetEnabledColor(text_color);
|
| + if (save_button_)
|
| + save_button_->SetEnabledTextColors(text_color);
|
| + if (discard_button_)
|
| + discard_button_->SetEnabledTextColors(text_color);
|
| }
|
|
|
| -void DownloadItemView::ShowContextMenuImpl(const gfx::Point& p,
|
| +void DownloadItemView::ShowContextMenuImpl(const gfx::Rect& rect,
|
| ui::MenuSourceType source_type) {
|
| - gfx::Point point = p;
|
| - gfx::Size size;
|
| -
|
| // Similar hack as in MenuButton.
|
| // We're about to show the menu from a mouse press. By showing from the
|
| // mouse press event we block RootView in mouse dispatching. This also
|
| @@ -975,125 +827,61 @@ void DownloadItemView::ShowContextMenuImpl(const gfx::Point& p,
|
| // matter where the user pressed. To force RootView to recalculate the
|
| // mouse target during the mouse press we explicitly set the mouse handler
|
| // to NULL.
|
| - static_cast<views::internal::RootView*>(GetWidget()->GetRootView())->
|
| - SetMouseHandler(NULL);
|
| -
|
| - // If |is_mouse_gesture| is false, |p| is ignored. The menu is shown aligned
|
| - // to drop down arrow button.
|
| - if (source_type != ui::MENU_SOURCE_MOUSE &&
|
| - source_type != ui::MENU_SOURCE_TOUCH) {
|
| - drop_down_pressed_ = true;
|
| - SetState(NORMAL, PUSHED);
|
| - point.SetPoint(drop_down_x_left_, box_y_);
|
| - size.SetSize(drop_down_x_right_ - drop_down_x_left_, box_height_);
|
| - }
|
| - views::View::ConvertPointToScreen(this, &point);
|
| + static_cast<views::internal::RootView*>(GetWidget()->GetRootView())
|
| + ->SetMouseHandler(NULL);
|
|
|
| if (!context_menu_.get())
|
| context_menu_.reset(new DownloadShelfContextMenuView(download()));
|
| -
|
| - context_menu_->Run(GetWidget()->GetTopLevelWidget(), gfx::Rect(point, size),
|
| - source_type, base::Bind(&DownloadItemView::ReleaseDropDown,
|
| - weak_ptr_factory_.GetWeakPtr()));
|
| + context_menu_->Run(GetWidget()->GetTopLevelWidget(), rect, source_type,
|
| + base::Bind(&DownloadItemView::ReleaseDropdown,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| }
|
|
|
| void DownloadItemView::HandlePressEvent(const ui::LocatedEvent& event,
|
| bool active_event) {
|
| - // The event should not activate us in dangerous mode.
|
| - if (mode_ == DANGEROUS_MODE)
|
| + // The event should not activate us in dangerous/malicious mode.
|
| + if (IsShowingWarningDialog())
|
| return;
|
|
|
| // Stop any completion animation.
|
| if (complete_animation_.get() && complete_animation_->is_animating())
|
| complete_animation_->End();
|
|
|
| - if (active_event) {
|
| - if (InDropDownButtonXCoordinateRange(event.x())) {
|
| - if (context_menu_.get()) {
|
| - // Ignore two close clicks. This typically happens when the user clicks
|
| - // the button to close the menu.
|
| - base::TimeDelta delta =
|
| - base::TimeTicks::Now() - context_menu_->close_time();
|
| - if (delta.InMilliseconds() < views::kMinimumMsBetweenButtonClicks)
|
| - return;
|
| - }
|
| - drop_down_pressed_ = true;
|
| - SetState(NORMAL, PUSHED);
|
| - // We are setting is_mouse_gesture to false when calling ShowContextMenu
|
| - // so that the positioning of the context menu will be similar to a
|
| - // keyboard invocation. I.e. we want the menu to always be positioned
|
| - // next to the drop down button instead of the next to the pointer.
|
| - ShowContextMenuImpl(event.location(), ui::MENU_SOURCE_KEYBOARD);
|
| - // Once called, it is possible that *this was deleted (e.g.: due to
|
| - // invoking the 'Discard' action.)
|
| - } else if (!IsShowingWarningDialog()) {
|
| - SetState(PUSHED, NORMAL);
|
| - }
|
| - }
|
| + // Don't show the ripple for right clicks.
|
| + if (!active_event)
|
| + return;
|
| +
|
| + AnimateInkDrop(views::InkDropState::ACTION_PENDING, &event);
|
| }
|
|
|
| void DownloadItemView::HandleClickEvent(const ui::LocatedEvent& event,
|
| bool active_event) {
|
| - // Mouse should not activate us in dangerous mode.
|
| - if (mode_ == DANGEROUS_MODE)
|
| + // The event should not activate us in dangerous/malicious mode.
|
| + if (!active_event || IsShowingWarningDialog())
|
| return;
|
|
|
| - SetState(NORMAL, NORMAL);
|
| -
|
| - if (!active_event ||
|
| - InDropDownButtonXCoordinateRange(event.x()) ||
|
| - IsShowingWarningDialog()) {
|
| - return;
|
| - }
|
| + AnimateInkDrop(views::InkDropState::ACTION_TRIGGERED, &event);
|
|
|
| // OpenDownload may delete this, so don't add any code after this line.
|
| OpenDownload();
|
| }
|
|
|
| -// Load an icon for the file type we're downloading, and animate any in progress
|
| -// download state.
|
| -void DownloadItemView::PaintImages(gfx::Canvas* canvas,
|
| - const gfx::ImageSkia* top_image,
|
| - const gfx::ImageSkia* center_image,
|
| - const gfx::ImageSkia* bottom_image,
|
| - int x, int y, int height, int width) {
|
| - int middle_height = height - top_image->height() - bottom_image->height();
|
| - // Draw the top.
|
| - canvas->DrawImageInt(*top_image,
|
| - 0, 0, top_image->width(), top_image->height(),
|
| - x, y, width, top_image->height(), false);
|
| - y += top_image->height();
|
| - // Draw the center.
|
| - canvas->DrawImageInt(*center_image,
|
| - 0, 0, center_image->width(), center_image->height(),
|
| - x, y, width, middle_height, false);
|
| - y += middle_height;
|
| - // Draw the bottom.
|
| - canvas->DrawImageInt(*bottom_image,
|
| - 0, 0, bottom_image->width(), bottom_image->height(),
|
| - x, y, width, bottom_image->height(), false);
|
| -}
|
| -
|
| -void DownloadItemView::SetState(State new_body_state, State new_drop_state) {
|
| - // If we are showing a warning dialog, we don't change body state.
|
| - if (IsShowingWarningDialog()) {
|
| - new_body_state = NORMAL;
|
| -
|
| - // Current body_state_ should always be NORMAL for warning dialogs.
|
| - DCHECK_EQ(NORMAL, body_state_);
|
| - // We shouldn't be calling SetState if we are in DANGEROUS_MODE.
|
| - DCHECK_NE(DANGEROUS_MODE, mode_);
|
| - }
|
| - // Avoid extra SchedulePaint()s if the state is going to be the same.
|
| - if (body_state_ == new_body_state && drop_down_state_ == new_drop_state)
|
| +void DownloadItemView::SetDropdownState(State new_state) {
|
| + // Avoid extra SchedulePaint()s if the state is going to be the same and
|
| + // |dropdown_button_| has already been initialized.
|
| + if (dropdown_state_ == new_state &&
|
| + !dropdown_button_->GetImage(views::CustomButton::STATE_NORMAL).isNull())
|
| return;
|
|
|
| - AnimateStateTransition(body_state_, new_body_state,
|
| - body_hover_animation_.get());
|
| - AnimateStateTransition(drop_down_state_, new_drop_state,
|
| - drop_hover_animation_.get());
|
| - body_state_ = new_body_state;
|
| - drop_down_state_ = new_drop_state;
|
| + dropdown_button_->SetIcon(new_state == PUSHED ? gfx::VectorIconId::FIND_NEXT
|
| + : gfx::VectorIconId::FIND_PREV);
|
| + if (new_state != dropdown_state_) {
|
| + dropdown_button_->AnimateInkDrop(new_state == PUSHED
|
| + ? views::InkDropState::ACTIVATED
|
| + : views::InkDropState::DEACTIVATED);
|
| + }
|
| + dropdown_button_->OnThemeChanged();
|
| + dropdown_state_ = new_state;
|
| SchedulePaint();
|
| }
|
|
|
| @@ -1103,7 +891,8 @@ void DownloadItemView::ToggleWarningDialog() {
|
| else
|
| ClearWarningDialog();
|
|
|
| - UpdateDropDownButtonPosition();
|
| + // We need to load the icon now that the download has the real path.
|
| + LoadIcon();
|
|
|
| // Force the shelf to layout again as our size has changed.
|
| shelf_->Layout();
|
| @@ -1113,11 +902,10 @@ void DownloadItemView::ToggleWarningDialog() {
|
| void DownloadItemView::ClearWarningDialog() {
|
| DCHECK(download()->GetDangerType() ==
|
| content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED);
|
| - DCHECK(mode_ == DANGEROUS_MODE || mode_ == MALICIOUS_MODE);
|
| + DCHECK(IsShowingWarningDialog());
|
|
|
| mode_ = NORMAL_MODE;
|
| - body_state_ = NORMAL;
|
| - drop_down_state_ = NORMAL;
|
| + dropdown_state_ = NORMAL;
|
|
|
| // ExperienceSampling: User proceeded through the warning.
|
| if (sampling_event_.get()) {
|
| @@ -1140,6 +928,8 @@ void DownloadItemView::ClearWarningDialog() {
|
|
|
| // We need to load the icon now that the download has the real path.
|
| LoadIcon();
|
| +
|
| + dropdown_button_->SetVisible(true);
|
| }
|
|
|
| void DownloadItemView::ShowWarningDialog() {
|
| @@ -1160,53 +950,54 @@ void DownloadItemView::ShowWarningDialog() {
|
| std::string event_name = model_.MightBeMalicious()
|
| ? ExperienceSamplingEvent::kMaliciousDownload
|
| : ExperienceSamplingEvent::kDangerousDownload;
|
| - sampling_event_.reset(
|
| - new ExperienceSamplingEvent(event_name,
|
| - download()->GetURL(),
|
| - download()->GetReferrerUrl(),
|
| - download()->GetBrowserContext()));
|
| -
|
| - body_state_ = NORMAL;
|
| - drop_down_state_ = NORMAL;
|
| + sampling_event_.reset(new ExperienceSamplingEvent(
|
| + event_name, download()->GetURL(), download()->GetReferrerUrl(),
|
| + download()->GetBrowserContext()));
|
| +
|
| + dropdown_state_ = NORMAL;
|
| if (mode_ == DANGEROUS_MODE) {
|
| - save_button_ = new views::LabelButton(
|
| - this, model_.GetWarningConfirmButtonText());
|
| - save_button_->SetStyle(views::Button::STYLE_BUTTON);
|
| + save_button_ =
|
| + views::MdTextButton::Create(this, model_.GetWarningConfirmButtonText());
|
| AddChildView(save_button_);
|
| }
|
| - discard_button_ = new views::LabelButton(
|
| + discard_button_ = views::MdTextButton::Create(
|
| this, l10n_util::GetStringUTF16(IDS_DISCARD_DOWNLOAD));
|
| - discard_button_->SetStyle(views::Button::STYLE_BUTTON);
|
| AddChildView(discard_button_);
|
|
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| - switch (danger_type) {
|
| + base::string16 dangerous_label =
|
| + model_.GetWarningText(font_list_, kTextWidth);
|
| + dangerous_download_label_ = new views::Label(dangerous_label);
|
| + dangerous_download_label_->SetMultiLine(true);
|
| + dangerous_download_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| + dangerous_download_label_->SetAutoColorReadabilityEnabled(false);
|
| + AddChildView(dangerous_download_label_);
|
| + SizeLabelToMinWidth();
|
| +
|
| + dropdown_button_->SetVisible(mode_ == MALICIOUS_MODE);
|
| +}
|
| +
|
| +gfx::ImageSkia DownloadItemView::GetWarningIcon() {
|
| + switch (download()->GetDangerType()) {
|
| case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
|
| case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
|
| case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
|
| case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
|
| case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
|
| - warning_icon_ = rb.GetImageSkiaNamed(IDR_SAFEBROWSING_WARNING);
|
| - break;
|
| + return gfx::CreateVectorIcon(gfx::VectorIconId::REMOVE_CIRCLE,
|
| + kWarningIconSize, gfx::kGoogleRed700);
|
|
|
| case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
|
| case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
|
| case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
|
| case content::DOWNLOAD_DANGER_TYPE_MAX:
|
| NOTREACHED();
|
| - // fallthrough
|
| + break;
|
|
|
| case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
|
| - warning_icon_ = rb.GetImageSkiaNamed(IDR_WARNING);
|
| + return gfx::CreateVectorIcon(gfx::VectorIconId::WARNING, kWarningIconSize,
|
| + gfx::kGoogleYellow700);
|
| }
|
| - base::string16 dangerous_label =
|
| - model_.GetWarningText(font_list_, kTextWidth);
|
| - dangerous_download_label_ = new views::Label(dangerous_label);
|
| - dangerous_download_label_->SetMultiLine(true);
|
| - dangerous_download_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| - dangerous_download_label_->SetAutoColorReadabilityEnabled(false);
|
| - AddChildView(dangerous_download_label_);
|
| - SizeLabelToMinWidth();
|
| + return gfx::ImageSkia();
|
| }
|
|
|
| gfx::Size DownloadItemView::GetButtonSize() const {
|
| @@ -1278,7 +1069,7 @@ void DownloadItemView::SizeLabelToMinWidth() {
|
| prev_text = current_text;
|
| }
|
|
|
| - dangerous_download_label_->SetBounds(0, 0, size.width(), size.height());
|
| + dangerous_download_label_->SetSize(size);
|
| dangerous_download_label_sized_ = true;
|
| }
|
|
|
| @@ -1287,15 +1078,8 @@ void DownloadItemView::Reenable() {
|
| SetEnabled(true); // Triggers a repaint.
|
| }
|
|
|
| -void DownloadItemView::ReleaseDropDown() {
|
| - drop_down_pressed_ = false;
|
| - SetState(NORMAL, NORMAL);
|
| -}
|
| -
|
| -bool DownloadItemView::InDropDownButtonXCoordinateRange(int x) {
|
| - if (x > drop_down_x_left_ && x < drop_down_x_right_)
|
| - return true;
|
| - return false;
|
| +void DownloadItemView::ReleaseDropdown() {
|
| + SetDropdownState(NORMAL);
|
| }
|
|
|
| void DownloadItemView::UpdateAccessibleName() {
|
| @@ -1304,7 +1088,7 @@ void DownloadItemView::UpdateAccessibleName() {
|
| new_name = dangerous_download_label_->text();
|
| } else {
|
| new_name = status_text_ + base::char16(' ') +
|
| - download()->GetFileNameToReportUser().LossyDisplayName();
|
| + download()->GetFileNameToReportUser().LossyDisplayName();
|
| }
|
|
|
| // If the name has changed, notify assistive technology that the name
|
| @@ -1315,21 +1099,8 @@ void DownloadItemView::UpdateAccessibleName() {
|
| }
|
| }
|
|
|
| -void DownloadItemView::UpdateDropDownButtonPosition() {
|
| - gfx::Size size = GetPreferredSize();
|
| - if (base::i18n::IsRTL()) {
|
| - // Drop down button is glued to the left of the download shelf.
|
| - drop_down_x_left_ = 0;
|
| - drop_down_x_right_ = normal_drop_down_image_set_.top->width();
|
| - } else {
|
| - // Drop down button is glued to the right of the download shelf.
|
| - drop_down_x_left_ =
|
| - size.width() - normal_drop_down_image_set_.top->width();
|
| - drop_down_x_right_ = size.width();
|
| - }
|
| -}
|
| -
|
| -void DownloadItemView::AnimateStateTransition(State from, State to,
|
| +void DownloadItemView::AnimateStateTransition(State from,
|
| + State to,
|
| gfx::SlideAnimation* animation) {
|
| if (from == NORMAL && to == HOT) {
|
| animation->Show();
|
| @@ -1346,3 +1117,11 @@ void DownloadItemView::ProgressTimerFired() {
|
| if (model_.PercentComplete() < 0)
|
| SchedulePaint();
|
| }
|
| +
|
| +SkColor DownloadItemView::GetTextColor() const {
|
| + return GetTextColorForThemeProvider(GetThemeProvider());
|
| +}
|
| +
|
| +SkColor DownloadItemView::GetDimmedTextColor() const {
|
| + return SkColorSetA(GetTextColor(), 0xC7);
|
| +}
|
|
|