OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/gtk/download/download_item_gtk.h" | 5 #include "chrome/browser/ui/gtk/download/download_item_gtk.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 G_CALLBACK(OnButtonPressThunk), this); | 118 G_CALLBACK(OnButtonPressThunk), this); |
119 GTK_WIDGET_UNSET_FLAGS(body_.get(), GTK_CAN_FOCUS); | 119 GTK_WIDGET_UNSET_FLAGS(body_.get(), GTK_CAN_FOCUS); |
120 // Remove internal padding on the button. | 120 // Remove internal padding on the button. |
121 GtkRcStyle* no_padding_style = gtk_rc_style_new(); | 121 GtkRcStyle* no_padding_style = gtk_rc_style_new(); |
122 no_padding_style->xthickness = 0; | 122 no_padding_style->xthickness = 0; |
123 no_padding_style->ythickness = 0; | 123 no_padding_style->ythickness = 0; |
124 gtk_widget_modify_style(body_.get(), no_padding_style); | 124 gtk_widget_modify_style(body_.get(), no_padding_style); |
125 g_object_unref(no_padding_style); | 125 g_object_unref(no_padding_style); |
126 | 126 |
127 name_label_ = gtk_label_new(NULL); | 127 name_label_ = gtk_label_new(NULL); |
| 128 // Left align and vertically center the labels. |
| 129 gtk_misc_set_alignment(GTK_MISC(name_label_), 0, 0.5); |
| 130 // Until we switch to vector graphics, force the font size. |
| 131 gtk_util::ForceFontSizePixels(name_label_, kTextSize); |
128 | 132 |
129 UpdateNameLabel(); | 133 UpdateNameLabel(); |
130 | 134 |
131 status_label_ = gtk_label_new(NULL); | 135 status_label_ = NULL; |
132 g_signal_connect(status_label_, "destroy", | |
133 G_CALLBACK(gtk_widget_destroyed), &status_label_); | |
134 // Left align and vertically center the labels. | |
135 gtk_misc_set_alignment(GTK_MISC(name_label_), 0, 0.5); | |
136 gtk_misc_set_alignment(GTK_MISC(status_label_), 0, 0.5); | |
137 // Until we switch to vector graphics, force the font size. | |
138 gtk_util::ForceFontSizePixels(name_label_, kTextSize); | |
139 gtk_util::ForceFontSizePixels(status_label_, kTextSize); | |
140 | 136 |
141 // Stack the labels on top of one another. | 137 // Stack the labels on top of one another. |
142 GtkWidget* text_stack = gtk_vbox_new(FALSE, 0); | 138 text_stack_ = gtk_vbox_new(FALSE, 0); |
143 gtk_box_pack_start(GTK_BOX(text_stack), name_label_, TRUE, TRUE, 0); | 139 gtk_box_pack_start(GTK_BOX(text_stack_), name_label_, TRUE, TRUE, 0); |
144 gtk_box_pack_start(GTK_BOX(text_stack), status_label_, FALSE, FALSE, 0); | |
145 | 140 |
146 // We use a GtkFixed because we don't want it to have its own window. | 141 // We use a GtkFixed because we don't want it to have its own window. |
147 // This choice of widget is not critically important though. | 142 // This choice of widget is not critically important though. |
148 progress_area_.Own(gtk_fixed_new()); | 143 progress_area_.Own(gtk_fixed_new()); |
149 gtk_widget_set_size_request(progress_area_.get(), | 144 gtk_widget_set_size_request(progress_area_.get(), |
150 download_util::kSmallProgressIconSize, | 145 download_util::kSmallProgressIconSize, |
151 download_util::kSmallProgressIconSize); | 146 download_util::kSmallProgressIconSize); |
152 gtk_widget_set_app_paintable(progress_area_.get(), TRUE); | 147 gtk_widget_set_app_paintable(progress_area_.get(), TRUE); |
153 g_signal_connect(progress_area_.get(), "expose-event", | 148 g_signal_connect(progress_area_.get(), "expose-event", |
154 G_CALLBACK(OnProgressAreaExposeThunk), this); | 149 G_CALLBACK(OnProgressAreaExposeThunk), this); |
155 | 150 |
156 // Put the download progress icon on the left of the labels. | 151 // Put the download progress icon on the left of the labels. |
157 GtkWidget* body_hbox = gtk_hbox_new(FALSE, 0); | 152 GtkWidget* body_hbox = gtk_hbox_new(FALSE, 0); |
158 gtk_container_add(GTK_CONTAINER(body_.get()), body_hbox); | 153 gtk_container_add(GTK_CONTAINER(body_.get()), body_hbox); |
159 gtk_box_pack_start(GTK_BOX(body_hbox), progress_area_.get(), FALSE, FALSE, 0); | 154 gtk_box_pack_start(GTK_BOX(body_hbox), progress_area_.get(), FALSE, FALSE, 0); |
160 gtk_box_pack_start(GTK_BOX(body_hbox), text_stack, TRUE, TRUE, 0); | 155 gtk_box_pack_start(GTK_BOX(body_hbox), text_stack_, TRUE, TRUE, 0); |
161 | 156 |
162 menu_button_ = gtk_button_new(); | 157 menu_button_ = gtk_button_new(); |
163 gtk_widget_set_app_paintable(menu_button_, TRUE); | 158 gtk_widget_set_app_paintable(menu_button_, TRUE); |
164 GTK_WIDGET_UNSET_FLAGS(menu_button_, GTK_CAN_FOCUS); | 159 GTK_WIDGET_UNSET_FLAGS(menu_button_, GTK_CAN_FOCUS); |
165 g_signal_connect(menu_button_, "expose-event", | 160 g_signal_connect(menu_button_, "expose-event", |
166 G_CALLBACK(OnExposeThunk), this); | 161 G_CALLBACK(OnExposeThunk), this); |
167 g_signal_connect(menu_button_, "button-press-event", | 162 g_signal_connect(menu_button_, "button-press-event", |
168 G_CALLBACK(OnMenuButtonPressEventThunk), this); | 163 G_CALLBACK(OnMenuButtonPressEventThunk), this); |
169 g_object_set_data(G_OBJECT(menu_button_), "left-align-popup", | 164 g_object_set_data(G_OBJECT(menu_button_), "left-align-popup", |
170 reinterpret_cast<void*>(true)); | 165 reinterpret_cast<void*>(true)); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 download_complete_ = true; | 337 download_complete_ = true; |
343 break; | 338 break; |
344 case DownloadItem::IN_PROGRESS: | 339 case DownloadItem::IN_PROGRESS: |
345 get_download()->is_paused() ? | 340 get_download()->is_paused() ? |
346 StopDownloadProgress() : StartDownloadProgress(); | 341 StopDownloadProgress() : StartDownloadProgress(); |
347 break; | 342 break; |
348 default: | 343 default: |
349 NOTREACHED(); | 344 NOTREACHED(); |
350 } | 345 } |
351 | 346 |
352 // Now update the status label. We may have already removed it; if so, we | |
353 // do nothing. | |
354 if (!status_label_) { | |
355 return; | |
356 } | |
357 | |
358 status_text_ = UTF16ToUTF8(download_model_->GetStatusText()); | 347 status_text_ = UTF16ToUTF8(download_model_->GetStatusText()); |
359 // Remove the status text label. | |
360 if (status_text_.empty()) { | |
361 gtk_widget_destroy(status_label_); | |
362 return; | |
363 } | |
364 | |
365 UpdateStatusLabel(status_text_); | 348 UpdateStatusLabel(status_text_); |
366 } | 349 } |
367 | 350 |
368 void DownloadItemGtk::AnimationProgressed(const ui::Animation* animation) { | 351 void DownloadItemGtk::AnimationProgressed(const ui::Animation* animation) { |
369 if (animation == &complete_animation_) { | 352 if (animation == &complete_animation_) { |
370 gtk_widget_queue_draw(progress_area_.get()); | 353 gtk_widget_queue_draw(progress_area_.get()); |
371 } else { | 354 } else { |
372 DCHECK(animation == new_item_animation_.get()); | 355 DCHECK(animation == new_item_animation_.get()); |
373 if (IsDangerous()) { | 356 if (IsDangerous()) { |
374 int progress = static_cast<int>((dangerous_hbox_full_width_ - | 357 int progress = static_cast<int>((dangerous_hbox_full_width_ - |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
491 GdkColor color = theme_service_->GetGdkColor( | 474 GdkColor color = theme_service_->GetGdkColor( |
492 ThemeService::COLOR_BOOKMARK_TEXT); | 475 ThemeService::COLOR_BOOKMARK_TEXT); |
493 gtk_util::SetLabelColor( | 476 gtk_util::SetLabelColor( |
494 name_label_, | 477 name_label_, |
495 theme_service_->UsingNativeTheme() ? NULL : &color); | 478 theme_service_->UsingNativeTheme() ? NULL : &color); |
496 gtk_label_set_text(GTK_LABEL(name_label_), | 479 gtk_label_set_text(GTK_LABEL(name_label_), |
497 UTF16ToUTF8(elided_filename).c_str()); | 480 UTF16ToUTF8(elided_filename).c_str()); |
498 } | 481 } |
499 | 482 |
500 void DownloadItemGtk::UpdateStatusLabel(const std::string& status_text) { | 483 void DownloadItemGtk::UpdateStatusLabel(const std::string& status_text) { |
501 if (!status_label_) | 484 // If |status_text| is empty, only |name_label_| is displayed at the |
| 485 // vertical center of |text_stack_|. Otherwise, |name_label_| is displayed |
| 486 // on the upper half of |text_stack_| and |status_label_| is displayed |
| 487 // on the lower half of |text_stack_|. |
| 488 if (status_text.empty() && status_label_) { |
| 489 gtk_widget_destroy(status_label_); |
502 return; | 490 return; |
| 491 } |
| 492 if (!status_label_) { |
| 493 status_label_ = gtk_label_new(NULL); |
| 494 g_signal_connect(status_label_, "destroy", |
| 495 G_CALLBACK(gtk_widget_destroyed), &status_label_); |
| 496 // Left align and vertically center the labels. |
| 497 gtk_misc_set_alignment(GTK_MISC(status_label_), 0, 0.5); |
| 498 // Until we switch to vector graphics, force the font size. |
| 499 gtk_util::ForceFontSizePixels(status_label_, kTextSize); |
| 500 |
| 501 gtk_box_pack_start(GTK_BOX(text_stack_), status_label_, FALSE, FALSE, 0); |
| 502 gtk_widget_show_all(hbox_.get()); |
| 503 } |
503 | 504 |
504 GdkColor text_color; | 505 GdkColor text_color; |
505 if (!theme_service_->UsingNativeTheme()) { | 506 if (!theme_service_->UsingNativeTheme()) { |
506 SkColor color = theme_service_->GetColor( | 507 SkColor color = theme_service_->GetColor( |
507 ThemeService::COLOR_BOOKMARK_TEXT); | 508 ThemeService::COLOR_BOOKMARK_TEXT); |
508 if (color_utils::RelativeLuminance(color) > 0.5) { | 509 if (color_utils::RelativeLuminance(color) > 0.5) { |
509 color = SkColorSetRGB( | 510 color = SkColorSetRGB( |
510 static_cast<int>(kDownloadItemLuminanceMod * | 511 static_cast<int>(kDownloadItemLuminanceMod * |
511 SkColorGetR(color)), | 512 SkColorGetR(color)), |
512 static_cast<int>(kDownloadItemLuminanceMod * | 513 static_cast<int>(kDownloadItemLuminanceMod * |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
778 get_download()->OpenDownload(); | 779 get_download()->OpenDownload(); |
779 parent_shelf_->ItemOpened(); | 780 parent_shelf_->ItemOpened(); |
780 } | 781 } |
781 | 782 |
782 gboolean DownloadItemGtk::OnButtonPress(GtkWidget* button, | 783 gboolean DownloadItemGtk::OnButtonPress(GtkWidget* button, |
783 GdkEventButton* event) { | 784 GdkEventButton* event) { |
784 if (event->type == GDK_BUTTON_PRESS && event->button == 3) { | 785 if (event->type == GDK_BUTTON_PRESS && event->button == 3) { |
785 ShowPopupMenu(NULL, event); | 786 ShowPopupMenu(NULL, event); |
786 return TRUE; | 787 return TRUE; |
787 } | 788 } |
788 | |
789 return FALSE; | 789 return FALSE; |
790 } | 790 } |
791 | 791 |
792 gboolean DownloadItemGtk::OnProgressAreaExpose(GtkWidget* widget, | 792 gboolean DownloadItemGtk::OnProgressAreaExpose(GtkWidget* widget, |
793 GdkEventExpose* event) { | 793 GdkEventExpose* event) { |
794 // Create a transparent canvas. | 794 // Create a transparent canvas. |
795 gfx::CanvasSkiaPaint canvas(event, false); | 795 gfx::CanvasSkiaPaint canvas(event, false); |
796 if (complete_animation_.is_animating()) { | 796 if (complete_animation_.is_animating()) { |
797 if (get_download()->IsInterrupted()) { | 797 if (get_download()->IsInterrupted()) { |
798 download_util::PaintDownloadInterrupted(&canvas, | 798 download_util::PaintDownloadInterrupted(&canvas, |
(...skipping 27 matching lines...) Expand all Loading... |
826 } | 826 } |
827 | 827 |
828 gboolean DownloadItemGtk::OnMenuButtonPressEvent(GtkWidget* button, | 828 gboolean DownloadItemGtk::OnMenuButtonPressEvent(GtkWidget* button, |
829 GdkEventButton* event) { | 829 GdkEventButton* event) { |
830 if (event->type == GDK_BUTTON_PRESS && event->button == 1) { | 830 if (event->type == GDK_BUTTON_PRESS && event->button == 1) { |
831 ShowPopupMenu(button, event); | 831 ShowPopupMenu(button, event); |
832 menu_showing_ = true; | 832 menu_showing_ = true; |
833 gtk_widget_queue_draw(button); | 833 gtk_widget_queue_draw(button); |
834 return TRUE; | 834 return TRUE; |
835 } | 835 } |
836 | |
837 return FALSE; | 836 return FALSE; |
838 } | 837 } |
839 | 838 |
840 void DownloadItemGtk::ShowPopupMenu(GtkWidget* button, | 839 void DownloadItemGtk::ShowPopupMenu(GtkWidget* button, |
841 GdkEventButton* event) { | 840 GdkEventButton* event) { |
842 // Stop any completion animation. | 841 // Stop any completion animation. |
843 if (complete_animation_.is_animating()) | 842 if (complete_animation_.is_animating()) |
844 complete_animation_.End(); | 843 complete_animation_.End(); |
845 | 844 |
846 if (!menu_.get()) | 845 if (!menu_.get()) |
(...skipping 16 matching lines...) Expand all Loading... |
863 get_download()->DangerousDownloadValidated(); | 862 get_download()->DangerousDownloadValidated(); |
864 } | 863 } |
865 | 864 |
866 void DownloadItemGtk::OnDangerousDecline(GtkWidget* button) { | 865 void DownloadItemGtk::OnDangerousDecline(GtkWidget* button) { |
867 UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download", | 866 UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download", |
868 base::Time::Now() - creation_time_); | 867 base::Time::Now() - creation_time_); |
869 if (get_download()->IsPartialDownload()) | 868 if (get_download()->IsPartialDownload()) |
870 get_download()->Cancel(true); | 869 get_download()->Cancel(true); |
871 get_download()->Delete(DownloadItem::DELETE_DUE_TO_USER_DISCARD); | 870 get_download()->Delete(DownloadItem::DELETE_DUE_TO_USER_DISCARD); |
872 } | 871 } |
OLD | NEW |