summaryrefslogtreecommitdiffstats
path: root/chrome/browser/gtk/download_item_gtk.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/gtk/download_item_gtk.cc')
-rw-r--r--chrome/browser/gtk/download_item_gtk.cc131
1 files changed, 113 insertions, 18 deletions
diff --git a/chrome/browser/gtk/download_item_gtk.cc b/chrome/browser/gtk/download_item_gtk.cc
index 42699e4..95db3c2 100644
--- a/chrome/browser/gtk/download_item_gtk.cc
+++ b/chrome/browser/gtk/download_item_gtk.cc
@@ -4,14 +4,17 @@
#include "chrome/browser/gtk/download_item_gtk.h"
+#include "app/gfx/chrome_canvas.h"
#include "app/gfx/chrome_font.h"
#include "app/gfx/text_elider.h"
#include "app/slide_animation.h"
#include "base/basictypes.h"
#include "base/string_util.h"
+#include "base/time.h"
#include "chrome/browser/download/download_item_model.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/download/download_shelf.h"
+#include "chrome/browser/download/download_util.h"
#include "chrome/browser/gtk/download_shelf_gtk.h"
#include "chrome/browser/gtk/menu_gtk.h"
#include "chrome/browser/gtk/nine_box.h"
@@ -31,14 +34,17 @@ const int kTextWidth = 140;
// The minimum width we will ever draw the download item. Used as a lower bound
// during animation. This number comes from the width of the images used to
// make the download item.
-const int kMinDownloadItemWidth = 13;
+const int kMinDownloadItemWidth = 13 + download_util::kSmallProgressIconSize;
const char* kLabelColorMarkup = "<span color='#%s'>%s</span>";
const char* kFilenameColor = "576C95"; // 87, 108, 149
const char* kStatusColor = "7B8DAE"; // 123, 141, 174
// New download item animation speed in milliseconds.
-static const int kNewItemAnimationDurationMs = 800;
+const int kNewItemAnimationDurationMs = 800;
+
+// How long the 'download complete' animation should last for.
+const int kCompleteAnimationDurationMs = 2500;
} // namespace
@@ -139,15 +145,23 @@ NineBox* DownloadItemGtk::menu_nine_box_active_ = NULL;
DownloadItemGtk::DownloadItemGtk(DownloadShelfGtk* parent_shelf,
BaseDownloadItemModel* download_model)
: parent_shelf_(parent_shelf),
+ progress_angle_(download_util::kStartAngleDegrees),
download_model_(download_model),
bounding_widget_(parent_shelf->GetRightBoundingWidget()) {
InitNineBoxes();
body_ = gtk_button_new();
gtk_widget_set_app_paintable(body_, TRUE);
- g_signal_connect(G_OBJECT(body_), "expose-event",
+ g_signal_connect(body_, "expose-event",
G_CALLBACK(OnExpose), this);
GTK_WIDGET_UNSET_FLAGS(body_, GTK_CAN_FOCUS);
+ // Remove internal padding on the button.
+ GtkRcStyle* no_padding_style = gtk_rc_style_new();
+ no_padding_style->xthickness = 0;
+ no_padding_style->ythickness = 0;
+ gtk_widget_modify_style(body_, no_padding_style);
+ g_object_unref(no_padding_style);
+
name_label_ = gtk_label_new(NULL);
// TODO(estade): This is at best an educated guess, since we don't actually
@@ -172,14 +186,29 @@ DownloadItemGtk::DownloadItemGtk(DownloadShelfGtk* parent_shelf,
GtkWidget* text_stack = gtk_vbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(text_stack), name_label_, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(text_stack), status_label_, FALSE, FALSE, 0);
- gtk_container_add(GTK_CONTAINER(body_), text_stack);
+
+ // We use a GtkFixed because we don't want it to have its own window.
+ // This choice of widget is not critically important though.
+ progress_area_ = gtk_fixed_new();
+ gtk_widget_set_size_request(progress_area_,
+ download_util::kSmallProgressIconSize,
+ download_util::kSmallProgressIconSize);
+ gtk_widget_set_app_paintable(progress_area_, TRUE);
+ g_signal_connect(progress_area_, "expose-event",
+ G_CALLBACK(OnProgressAreaExpose), this);
+
+ // Put the download progress icon on the left of the labels.
+ GtkWidget* body_hbox = gtk_hbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(body_), body_hbox);
+ gtk_box_pack_start(GTK_BOX(body_hbox), progress_area_, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(body_hbox), text_stack, TRUE, TRUE, 0);
menu_button_ = gtk_button_new();
gtk_widget_set_app_paintable(menu_button_, TRUE);
GTK_WIDGET_UNSET_FLAGS(menu_button_, GTK_CAN_FOCUS);
- g_signal_connect(G_OBJECT(menu_button_), "expose-event",
+ g_signal_connect(menu_button_, "expose-event",
G_CALLBACK(OnExpose), this);
- g_signal_connect(G_OBJECT(menu_button_), "button-press-event",
+ g_signal_connect(menu_button_, "button-press-event",
G_CALLBACK(OnMenuButtonPressEvent), this);
g_object_set_data(G_OBJECT(menu_button_), "left-align-popup",
reinterpret_cast<void*>(true));
@@ -205,6 +234,7 @@ DownloadItemGtk::DownloadItemGtk(DownloadShelfGtk* parent_shelf,
}
DownloadItemGtk::~DownloadItemGtk() {
+ StopDownloadProgress();
g_signal_handler_disconnect(parent_shelf_->GetHBox(), resize_handler_id_);
gtk_widget_destroy(hbox_);
download_model_->download()->RemoveObserver(this);
@@ -218,11 +248,18 @@ void DownloadItemGtk::OnDownloadUpdated(DownloadItem* download) {
parent_shelf_->RemoveDownloadItem(this); // This will delete us!
return;
case DownloadItem::CANCELLED:
+ StopDownloadProgress();
+ break;
case DownloadItem::COMPLETE:
+ StopDownloadProgress();
+ complete_animation_.reset(new SlideAnimation(this));
+ complete_animation_->SetSlideDuration(kCompleteAnimationDurationMs);
+ complete_animation_->SetTweenType(SlideAnimation::NONE);
+ complete_animation_->Show();
+ break;
case DownloadItem::IN_PROGRESS:
- // TODO(estade): adjust download progress animation appropriately, once
- // we have download progress animations.
- NOTIMPLEMENTED();
+ download_model_->download()->is_paused() ?
+ StopDownloadProgress() : StartDownloadProgress();
break;
default:
NOTREACHED();
@@ -250,15 +287,39 @@ void DownloadItemGtk::OnDownloadUpdated(DownloadItem* download) {
}
void DownloadItemGtk::AnimationProgressed(const Animation* animation) {
- // Eventually we will show an icon and graphical download progress, but for
- // now the only contents of body_ is text, so to make its size request the
- // same as the width of the text. See above TODO for explanation of the
- // extra 50.
- int showing_width = std::max(kMinDownloadItemWidth,
- static_cast<int>((kTextWidth + 50) *
- new_item_animation_->GetCurrentValue()));
- showing_width = std::max(showing_width, kMinDownloadItemWidth);
- gtk_widget_set_size_request(body_, showing_width, -1);
+ if (animation == complete_animation_.get()) {
+ gtk_widget_queue_draw(progress_area_);
+ } else {
+ DCHECK(animation == new_item_animation_.get());
+ // See above TODO for explanation of the extra 50.
+ int showing_width = std::max(kMinDownloadItemWidth,
+ static_cast<int>((kTextWidth + 50 +
+ download_util::kSmallProgressIconSize) *
+ new_item_animation_->GetCurrentValue()));
+ showing_width = std::max(showing_width, kMinDownloadItemWidth);
+ gtk_widget_set_size_request(body_, showing_width, -1);
+ }
+}
+
+// Download progress animation functions.
+
+void DownloadItemGtk::UpdateDownloadProgress() {
+ progress_angle_ = (progress_angle_ +
+ download_util::kUnknownIncrementDegrees) %
+ download_util::kMaxDegrees;
+ gtk_widget_queue_draw(progress_area_);
+}
+
+void DownloadItemGtk::StartDownloadProgress() {
+ if (progress_timer_.IsRunning())
+ return;
+ progress_timer_.Start(
+ base::TimeDelta::FromMilliseconds(download_util::kProgressRateMs), this,
+ &DownloadItemGtk::UpdateDownloadProgress);
+}
+
+void DownloadItemGtk::StopDownloadProgress() {
+ progress_timer_.Stop();
}
// static
@@ -337,9 +398,42 @@ gboolean DownloadItemGtk::OnExpose(GtkWidget* widget, GdkEventExpose* e,
return TRUE;
}
+// static
+gboolean DownloadItemGtk::OnProgressAreaExpose(GtkWidget* widget,
+ GdkEventExpose* event, DownloadItemGtk* download_item) {
+ // Create a transparent canvas.
+ ChromeCanvasPaint canvas(event, false);
+ if (download_item->complete_animation_.get()) {
+ if (download_item->complete_animation_->IsAnimating()) {
+ download_util::PaintDownloadComplete(&canvas,
+ widget->allocation.x, widget->allocation.y,
+ download_item->complete_animation_->GetCurrentValue(),
+ download_util::SMALL);
+ }
+ } else {
+ download_util::PaintDownloadProgress(&canvas,
+ widget->allocation.x, widget->allocation.y,
+ download_item->progress_angle_,
+ download_item->download_model_->download()->PercentComplete(),
+ download_util::SMALL);
+ }
+
+ // TODO(estade): paint download icon.
+ return TRUE;
+}
+
+// static
gboolean DownloadItemGtk::OnMenuButtonPressEvent(GtkWidget* button,
GdkEvent* event,
DownloadItemGtk* item) {
+ // Stop any completion animation.
+ if (item->complete_animation_.get() &&
+ item->complete_animation_->IsAnimating()) {
+ item->complete_animation_->End();
+ }
+
+ item->complete_animation_->End();
+
// TODO(port): this never puts the button into the "active" state,
// so this may need to be changed. See note in BrowserToolbarGtk.
if (event->type == GDK_BUTTON_PRESS) {
@@ -356,6 +450,7 @@ gboolean DownloadItemGtk::OnMenuButtonPressEvent(GtkWidget* button,
return FALSE;
}
+// static
void DownloadItemGtk::OnShelfResized(GtkWidget *widget,
GtkAllocation *allocation,
DownloadItemGtk* item) {