| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/gtk/download_shelf_gtk.h" | 5 #include "chrome/browser/cocoa/download_shelf_mac.h" |
| 6 | 6 |
| 7 #include "base/gfx/gtk_util.h" | 7 #import "chrome/browser/cocoa/download_shelf_controller.h" |
| 8 #include "chrome/browser/cocoa/download_item_mac.h" |
| 8 #include "chrome/browser/download/download_item_model.h" | 9 #include "chrome/browser/download/download_item_model.h" |
| 9 #include "chrome/browser/gtk/custom_button.h" | |
| 10 #include "chrome/browser/gtk/download_item_gtk.h" | |
| 11 #include "chrome/browser/tab_contents/tab_contents.h" | |
| 12 #include "chrome/common/l10n_util.h" | |
| 13 #include "chrome/common/resource_bundle.h" | |
| 14 #include "grit/generated_resources.h" | |
| 15 #include "grit/theme_resources.h" | |
| 16 | 10 |
| 17 namespace { | 11 namespace { |
| 18 | 12 |
| 19 // The height of the download items. Should be at least 28, as that is the | 13 // TODO(thakis): These are all temporary until there's a download item view |
| 20 // minimum height of their nineboxes. | |
| 21 const int kDownloadItemHeight = 38; | |
| 22 | 14 |
| 23 // Padding between the download widgets. | 15 // Border padding of a download item |
| 16 const int kDownloadItemBorderPadding = 4; |
| 17 |
| 18 // Width of a download item |
| 19 const int kDownloadItemWidth = 200; |
| 20 |
| 21 // Height of a download item |
| 22 const int kDownloadItemHeight = 32; |
| 23 |
| 24 // Horizontal padding between two download items |
| 24 const int kDownloadItemPadding = 10; | 25 const int kDownloadItemPadding = 10; |
| 25 | 26 |
| 26 // Padding between the top/bottom of the download widgets and the edge of the | |
| 27 // shelf. | |
| 28 const int kTopBottomPadding = 4; | |
| 29 | |
| 30 // Padding between the left side of the shelf and the first download item. | |
| 31 const int kLeftPadding = 2; | |
| 32 | |
| 33 // Padding between the right side of the shelf and the close button. | |
| 34 const int kRightPadding = 10; | |
| 35 | |
| 36 // The background color of the shelf. | |
| 37 static GdkColor kBackgroundColor = GDK_COLOR_RGB(230, 237, 244); | |
| 38 | |
| 39 // Border color (the top pixel of the shelf). | |
| 40 static GdkColor kBorderColor = GDK_COLOR_RGB(214, 214, 214); | |
| 41 | |
| 42 const char* kLinkMarkup = | |
| 43 "<u><span color=\"blue\">%s</span></u>"; | |
| 44 | |
| 45 gboolean OnLinkExpose(GtkWidget* widget, GdkEventExpose* e, void*) { | |
| 46 // Draw the link inside the button. | |
| 47 gtk_container_propagate_expose(GTK_CONTAINER(widget), | |
| 48 gtk_bin_get_child(GTK_BIN(widget)), | |
| 49 e); | |
| 50 // Don't let the button draw itself, ever. | |
| 51 return TRUE; | |
| 52 } | |
| 53 | |
| 54 // |button| and |box| are out parameters. The caller of this function will want | |
| 55 // to connect to the click event on |button|. |box| will be set to the highest | |
| 56 // level widget. | |
| 57 // TODO(estade): either figure out a way to use GtkLinkButton, or move this | |
| 58 // to base/gfx/gtk_util.cc | |
| 59 void MakeLinkButton(const char* text, GdkColor* background_color, | |
| 60 GtkWidget** button, GtkWidget** box) { | |
| 61 // We put a label in a button so we can connect to the click event. We put the | |
| 62 // button in an event box so we can attach a cursor to it. We don't let the | |
| 63 // button draw itself; catch all expose events to the button and pass them | |
| 64 // through to the label. We stick the event box in an hbox, and to the left of | |
| 65 // that pack the download icon. | |
| 66 // TODO(estade): the link should turn red during the user's click. | |
| 67 | |
| 68 GtkWidget* label = gtk_label_new(NULL); | |
| 69 char* markup = g_markup_printf_escaped(kLinkMarkup, text); | |
| 70 gtk_label_set_markup(GTK_LABEL(label), markup); | |
| 71 g_free(markup); | |
| 72 | |
| 73 *button = gtk_button_new(); | |
| 74 gtk_widget_set_app_paintable(GTK_WIDGET(*button), TRUE); | |
| 75 g_signal_connect(G_OBJECT(*button), "expose-event", | |
| 76 G_CALLBACK(OnLinkExpose), NULL); | |
| 77 gtk_container_add(GTK_CONTAINER(*button), label); | |
| 78 | |
| 79 *box = gtk_event_box_new(); | |
| 80 gtk_widget_modify_bg(*box, GTK_STATE_NORMAL, background_color); | |
| 81 gtk_container_add(GTK_CONTAINER(*box), *button); | |
| 82 } | |
| 83 | |
| 84 // This should be called only after |link_box| has been realized. | |
| 85 void AttachCursorToLinkButton(GtkWidget* link_box) { | |
| 86 GdkCursor* cursor = gdk_cursor_new(GDK_HAND2); | |
| 87 gdk_window_set_cursor(link_box->window, cursor); | |
| 88 gdk_cursor_unref(cursor); | |
| 89 } | |
| 90 | |
| 91 } // namespace | 27 } // namespace |
| 92 | 28 |
| 93 // static | 29 DownloadShelfMac::DownloadShelfMac(Browser* browser, |
| 94 DownloadShelf* DownloadShelf::Create(TabContents* tab_contents) { | 30 DownloadShelfController* controller) |
| 95 return new DownloadShelfGtk(tab_contents); | 31 : DownloadShelf(browser), |
| 96 } | 32 shelf_controller_(controller) { |
| 97 | |
| 98 DownloadShelfGtk::DownloadShelfGtk(TabContents* tab_contents) | |
| 99 : DownloadShelf(tab_contents), | |
| 100 is_showing_(false) { | |
| 101 // Logically, the shelf is a vbox that contains two children: a one pixel | |
| 102 // tall event box, which serves as the top border, and an hbox, which holds | |
| 103 // the download items and other shelf widgets (close button, show-all- | |
| 104 // downloads link). | |
| 105 // To make things pretty, we have to add a few more widgets. To get padding | |
| 106 // right, we stick the hbox in an alignment. We put that alignment in an | |
| 107 // event box so we can color the background. | |
| 108 | |
| 109 // Create the top border. | |
| 110 GtkWidget* top_border = gtk_event_box_new(); | |
| 111 gtk_widget_set_size_request(GTK_WIDGET(top_border), 0, 1); | |
| 112 gtk_widget_modify_bg(top_border, GTK_STATE_NORMAL, &kBorderColor); | |
| 113 | |
| 114 // Create |hbox_|. | |
| 115 hbox_ = gtk_hbox_new(FALSE, kDownloadItemPadding); | |
| 116 gtk_widget_set_size_request(hbox_, -1, kDownloadItemHeight); | |
| 117 | |
| 118 // Get the padding and background color for |hbox_| right. | |
| 119 GtkWidget* padding = gtk_alignment_new(0, 0, 1, 1); | |
| 120 // Subtract 1 from top spacing to account for top border. | |
| 121 gtk_alignment_set_padding(GTK_ALIGNMENT(padding), | |
| 122 kTopBottomPadding - 1, kTopBottomPadding, kLeftPadding, kRightPadding); | |
| 123 GtkWidget* padding_bg = gtk_event_box_new(); | |
| 124 gtk_container_add(GTK_CONTAINER(padding_bg), padding); | |
| 125 gtk_container_add(GTK_CONTAINER(padding), hbox_); | |
| 126 gtk_widget_modify_bg(padding_bg, GTK_STATE_NORMAL, &kBackgroundColor); | |
| 127 | |
| 128 shelf_ = gtk_vbox_new(FALSE, 0); | |
| 129 gtk_box_pack_start(GTK_BOX(shelf_), top_border, FALSE, FALSE, 0); | |
| 130 gtk_box_pack_start(GTK_BOX(shelf_), padding_bg, FALSE, FALSE, 0); | |
| 131 | |
| 132 // Create and pack the close button. | |
| 133 close_button_.reset(new CustomDrawButton(IDR_CLOSE_BAR, | |
| 134 IDR_CLOSE_BAR_P, IDR_CLOSE_BAR_H, 0)); | |
| 135 g_signal_connect(G_OBJECT(close_button_->widget()), "clicked", | |
| 136 G_CALLBACK(OnButtonClick), this); | |
| 137 GTK_WIDGET_UNSET_FLAGS(close_button_->widget(), GTK_CAN_FOCUS); | |
| 138 GtkWidget* centering_vbox = gtk_vbox_new(FALSE, 0); | |
| 139 gtk_box_pack_start(GTK_BOX(centering_vbox), | |
| 140 close_button_->widget(), TRUE, FALSE, 0); | |
| 141 gtk_box_pack_end(GTK_BOX(hbox_), centering_vbox, FALSE, FALSE, 0); | |
| 142 | |
| 143 // Create and pack the "Show all downloads..." link. | |
| 144 // TODO(estade): there are some pixels above and below the link that | |
| 145 // can be clicked. I tried to fix this with a vbox (akin to |centering_vbox| | |
| 146 // above), but no dice. | |
| 147 GtkWidget* link_box; | |
| 148 GtkWidget* link_button; | |
| 149 std::string link_text = | |
| 150 WideToUTF8(l10n_util::GetString(IDS_SHOW_ALL_DOWNLOADS)); | |
| 151 MakeLinkButton(link_text.c_str(), &kBackgroundColor, &link_button, &link_box); | |
| 152 g_signal_connect(G_OBJECT(link_button), "clicked", | |
| 153 G_CALLBACK(OnButtonClick), this); | |
| 154 | |
| 155 // Make the download arrow icon. | |
| 156 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
| 157 GdkPixbuf* download_pixbuf = rb.LoadPixbuf(IDR_DOWNLOADS_FAVICON); | |
| 158 GtkWidget* download_image = gtk_image_new_from_pixbuf(download_pixbuf); | |
| 159 gdk_pixbuf_unref(download_pixbuf); | |
| 160 | |
| 161 // Pack the link and the icon in an hbox. | |
| 162 link_hbox_ = gtk_hbox_new(FALSE, 0); | |
| 163 gtk_box_pack_start(GTK_BOX(link_hbox_), download_image, FALSE, FALSE, 0); | |
| 164 gtk_box_pack_start(GTK_BOX(link_hbox_), link_box, FALSE, FALSE, 0); | |
| 165 gtk_box_pack_end(GTK_BOX(hbox_), link_hbox_, FALSE, FALSE, 0); | |
| 166 | |
| 167 // Stick ourselves at the bottom of the parent tab contents. | |
| 168 GtkWidget* parent_contents = tab_contents->GetNativeView(); | |
| 169 gtk_box_pack_end(GTK_BOX(parent_contents), shelf_, FALSE, FALSE, 0); | |
| 170 Show(); | |
| 171 | |
| 172 AttachCursorToLinkButton(link_box); | |
| 173 } | |
| 174 | |
| 175 DownloadShelfGtk::~DownloadShelfGtk() { | |
| 176 } | |
| 177 | |
| 178 void DownloadShelfGtk::AddDownload(BaseDownloadItemModel* download_model_) { | |
| 179 // TODO(estade): we need to delete these at some point. There's no explicit | |
| 180 // mass delete on windows, figure out where they do it. | |
| 181 download_items_.push_back(new DownloadItemGtk(download_model_, hbox_, | |
| 182 link_hbox_)); | |
| 183 Show(); | 33 Show(); |
| 184 } | 34 } |
| 185 | 35 |
| 186 bool DownloadShelfGtk::IsShowing() const { | 36 void DownloadShelfMac::AddDownload(BaseDownloadItemModel* download_model) { |
| 187 return is_showing_; | 37 |
| 38 // TODO(thakis): we need to delete these at some point. There's no explicit |
| 39 // mass delete on windows, figure out where they do it. |
| 40 |
| 41 // TODO(thakis): This should just forward to the controller. |
| 42 |
| 43 // TODO(thakis): RTL support? |
| 44 int startX = kDownloadItemBorderPadding + |
| 45 (kDownloadItemWidth + kDownloadItemPadding) * download_items_.size(); |
| 46 download_items_.push_back(new DownloadItemMac(download_model, |
| 47 NSMakeRect(startX, kDownloadItemBorderPadding, |
| 48 kDownloadItemWidth, kDownloadItemHeight), |
| 49 shelf_controller_)); |
| 50 |
| 51 Show(); |
| 188 } | 52 } |
| 189 | 53 |
| 190 void DownloadShelfGtk::Show() { | 54 bool DownloadShelfMac::IsShowing() const { |
| 191 if (is_showing_) | 55 return [shelf_controller_ isVisible] == YES; |
| 192 return; | |
| 193 | |
| 194 gtk_widget_show_all(shelf_); | |
| 195 is_showing_ = true; | |
| 196 } | 56 } |
| 197 | 57 |
| 198 void DownloadShelfGtk::Hide() { | 58 bool DownloadShelfMac::IsClosing() const { |
| 199 if (!is_showing_) | 59 // TODO(estade): This is never called. For now just return false. |
| 200 return; | 60 return false; |
| 201 | |
| 202 gtk_widget_hide_all(shelf_); | |
| 203 is_showing_ = false; | |
| 204 } | 61 } |
| 205 | 62 |
| 206 // static | 63 void DownloadShelfMac::Show() { |
| 207 void DownloadShelfGtk::OnButtonClick(GtkWidget* button, | 64 [shelf_controller_ show:nil]; |
| 208 DownloadShelfGtk* shelf) { | |
| 209 if (button == shelf->close_button_->widget()) { | |
| 210 shelf->Hide(); | |
| 211 } else { | |
| 212 // The link button was clicked. | |
| 213 shelf->ShowAllDownloads(); | |
| 214 } | |
| 215 } | 65 } |
| 66 |
| 67 void DownloadShelfMac::Close() { |
| 68 [shelf_controller_ hide:nil]; |
| 69 } |
| OLD | NEW |