| 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_item_gtk.h" | 5 #include "chrome/browser/cocoa/download_item_mac.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
| 9 #include "base/sys_string_conversions.h" |
| 10 #import "chrome/browser/cocoa/download_shelf_controller.h" |
| 11 #import "chrome/browser/cocoa/download_shelf_mac.h" |
| 12 #import "chrome/browser/cocoa/download_shelf_view.h" |
| 9 #include "chrome/browser/download/download_item_model.h" | 13 #include "chrome/browser/download/download_item_model.h" |
| 10 #include "chrome/browser/download/download_manager.h" | 14 #include "chrome/browser/download/download_manager.h" |
| 11 #include "chrome/browser/download/download_shelf.h" | 15 #include "chrome/browser/download/download_shelf.h" |
| 12 #include "chrome/browser/gtk/menu_gtk.h" | |
| 13 #include "chrome/browser/gtk/nine_box.h" | |
| 14 #include "chrome/common/gfx/chrome_font.h" | |
| 15 #include "chrome/common/gfx/text_elider.h" | |
| 16 #include "chrome/common/resource_bundle.h" | |
| 17 #include "grit/generated_resources.h" | |
| 18 #include "grit/theme_resources.h" | |
| 19 | 16 |
| 20 namespace { | 17 // A class for the chromium-side part of the download shelf context menu. |
| 21 | 18 |
| 22 // The width of the |menu_button_| widget. It has to be at least as wide as the | 19 class DownloadShelfContextMenuMac : public DownloadShelfContextMenu { |
| 23 // bitmap that we use to draw it, i.e. 16, but can be more. | |
| 24 const int kMenuButtonWidth = 16; | |
| 25 | |
| 26 // Amount of space we allot to showing the filename. If the filename is too wide | |
| 27 // it will be elided. | |
| 28 const int kTextWidth = 140; | |
| 29 | |
| 30 const char* kLabelColorMarkup = "<span color='#%s'>%s</span>"; | |
| 31 const char* kFilenameColor = "576C95"; // 87, 108, 149 | |
| 32 const char* kStatusColor = "7B8DAE"; // 123, 141, 174 | |
| 33 | |
| 34 } // namespace | |
| 35 | |
| 36 // DownloadShelfContextMenuGtk ------------------------------------------------- | |
| 37 | |
| 38 class DownloadShelfContextMenuGtk : public DownloadShelfContextMenu, | |
| 39 public MenuGtk::Delegate { | |
| 40 public: | 20 public: |
| 41 // The constructor creates the menu and immediately pops it up. | 21 DownloadShelfContextMenuMac(BaseDownloadItemModel* model, |
| 42 // |model| is the download item model associated with this context menu, | 22 DownloadShelfContextMenuBridge* bridge) |
| 43 // |widget| is the button that popped up this context menu, and |e| is | 23 : DownloadShelfContextMenu(model), bridge_(bridge) { |
| 44 // the button press event that caused this menu to be created. | |
| 45 DownloadShelfContextMenuGtk(BaseDownloadItemModel* model) | |
| 46 : DownloadShelfContextMenu(model), | |
| 47 menu_is_for_complete_download_(false) { | |
| 48 } | 24 } |
| 49 | 25 |
| 50 ~DownloadShelfContextMenuGtk() { | 26 NSMenu* GetCocoaMenu(); |
| 51 } | |
| 52 | 27 |
| 53 void Popup(GtkWidget* widget, GdkEvent* event) { | 28 using DownloadShelfContextMenu::ExecuteItemCommand; |
| 54 // Create the menu if we have not created it yet or we created it for | |
| 55 // an in-progress download that has since completed. | |
| 56 bool download_is_complete = download_->state() == DownloadItem::COMPLETE; | |
| 57 if (menu_.get() == NULL || | |
| 58 (download_is_complete && !menu_is_for_complete_download_)) { | |
| 59 menu_.reset(new MenuGtk(this, download_is_complete ? | |
| 60 finished_download_menu : in_progress_download_menu, NULL)); | |
| 61 menu_is_for_complete_download_ = download_is_complete; | |
| 62 } | |
| 63 menu_->Popup(widget, event); | |
| 64 } | |
| 65 | |
| 66 // MenuGtk::Delegate implementation ------------------------------------------ | |
| 67 virtual bool IsCommandEnabled(int id) const { | |
| 68 return IsItemCommandEnabled(id); | |
| 69 } | |
| 70 | |
| 71 virtual bool IsItemChecked(int id) const { | |
| 72 return ItemIsChecked(id); | |
| 73 } | |
| 74 | |
| 75 virtual void ExecuteCommand(int id) { | |
| 76 return ExecuteItemCommand(id); | |
| 77 } | |
| 78 | 29 |
| 79 private: | 30 private: |
| 80 // The menu we show on Popup(). We keep a pointer to it for a couple reasons: | 31 DownloadShelfContextMenuBridge* bridge_; // weak, owns us |
| 81 // * we don't want to have to recreate the menu every time it's popped up. | |
| 82 // * we have to keep it in scope for longer than the duration of Popup(), or | |
| 83 // completing the user-selected action races against the menu's | |
| 84 // destruction. | |
| 85 scoped_ptr<MenuGtk> menu_; | |
| 86 | |
| 87 // If true, the MenuGtk in |menu_| refers to a finished download menu. | |
| 88 bool menu_is_for_complete_download_; | |
| 89 | |
| 90 // We show slightly different menus if the download is in progress vs. if the | |
| 91 // download has finished. | |
| 92 static MenuCreateMaterial in_progress_download_menu[]; | |
| 93 | |
| 94 static MenuCreateMaterial finished_download_menu[]; | |
| 95 }; | 32 }; |
| 96 | 33 |
| 97 MenuCreateMaterial DownloadShelfContextMenuGtk::finished_download_menu[] = { | 34 NSMenu* DownloadShelfContextMenuMac::GetCocoaMenu() { |
| 98 { MENU_NORMAL, OPEN_WHEN_COMPLETE, IDS_DOWNLOAD_MENU_OPEN, 0, NULL }, | 35 // TODO(thakis): win/gtk show slightly different menus when the download is |
| 99 { MENU_CHECKBOX, ALWAYS_OPEN_TYPE, IDS_DOWNLOAD_MENU_ALWAYS_OPEN_TYPE, | 36 // in progress/done (mainly the first item) |
| 100 0, NULL}, | 37 // TODO(thakis): this probably wants to be in a xib file or at least use |
| 101 { MENU_SEPARATOR, 0, 0, 0, NULL }, | 38 // localized strings |
| 102 { MENU_NORMAL, SHOW_IN_FOLDER, IDS_DOWNLOAD_LINK_SHOW, 0, NULL}, | |
| 103 { MENU_SEPARATOR, 0, 0, 0, NULL }, | |
| 104 { MENU_NORMAL, CANCEL, IDS_DOWNLOAD_MENU_CANCEL, 0, NULL}, | |
| 105 { MENU_END, 0, 0, 0, NULL }, | |
| 106 }; | |
| 107 | 39 |
| 108 MenuCreateMaterial DownloadShelfContextMenuGtk::in_progress_download_menu[] = { | 40 NSMenuItem* item; |
| 109 { MENU_CHECKBOX, OPEN_WHEN_COMPLETE, IDS_DOWNLOAD_MENU_OPEN_WHEN_COMPLETE, | 41 NSMenu* menu = |
| 110 0, NULL }, | 42 [[[NSMenu alloc] initWithTitle:@"DownloadItemPopup"] autorelease]; |
| 111 { MENU_CHECKBOX, ALWAYS_OPEN_TYPE, IDS_DOWNLOAD_MENU_ALWAYS_OPEN_TYPE, | 43 SEL action = @selector(performAction:); |
| 112 0, NULL}, | |
| 113 { MENU_SEPARATOR, 0, 0, 0, NULL }, | |
| 114 { MENU_NORMAL, SHOW_IN_FOLDER, IDS_DOWNLOAD_LINK_SHOW, 0, NULL}, | |
| 115 { MENU_SEPARATOR, 0, 0, 0, NULL }, | |
| 116 { MENU_NORMAL, CANCEL, IDS_DOWNLOAD_MENU_CANCEL, 0, NULL}, | |
| 117 { MENU_END, 0, 0, 0, NULL }, | |
| 118 }; | |
| 119 | 44 |
| 120 // DownloadItemGtk ------------------------------------------------------------- | 45 item = [menu addItemWithTitle:@"Open" action:action keyEquivalent:@""]; |
| 46 // [item addItemWithTitle:@"Open when complete" ...]; // In-progress text. |
| 47 [item setTag:OPEN_WHEN_COMPLETE]; |
| 48 [item setTarget:bridge_]; |
| 121 | 49 |
| 122 NineBox* DownloadItemGtk::body_nine_box_normal_ = NULL; | 50 // TODO(thakis): Set correct checkbox state, make this a checkbox item |
| 123 NineBox* DownloadItemGtk::body_nine_box_prelight_ = NULL; | 51 item = [menu addItemWithTitle:@"Always open type" |
| 124 NineBox* DownloadItemGtk::body_nine_box_active_ = NULL; | 52 action:action |
| 53 keyEquivalent:@""]; |
| 54 [item setTag:ALWAYS_OPEN_TYPE]; |
| 55 [item setTarget:bridge_]; |
| 125 | 56 |
| 126 NineBox* DownloadItemGtk::menu_nine_box_normal_ = NULL; | 57 [menu addItem:[NSMenuItem separatorItem]]; |
| 127 NineBox* DownloadItemGtk::menu_nine_box_prelight_ = NULL; | |
| 128 NineBox* DownloadItemGtk::menu_nine_box_active_ = NULL; | |
| 129 | 58 |
| 130 DownloadItemGtk::DownloadItemGtk(BaseDownloadItemModel* download_model, | 59 item = [menu addItemWithTitle:@"Reveal in Finder" |
| 131 GtkWidget* parent_shelf, | 60 action:action |
| 132 GtkWidget* bounding_widget) | 61 keyEquivalent:@""]; |
| 133 : download_model_(download_model), | 62 [item setTag:SHOW_IN_FOLDER]; |
| 134 parent_shelf_(parent_shelf), | 63 [item setTarget:bridge_]; |
| 135 bounding_widget_(bounding_widget) { | |
| 136 InitNineBoxes(); | |
| 137 | 64 |
| 138 body_ = gtk_button_new(); | 65 [menu addItem:[NSMenuItem separatorItem]]; |
| 139 // Eventually we will show an icon and graphical download progress, but for | |
| 140 // now the only contents of body_ is text, so to make its size request the | |
| 141 // same as the width of the text (plus a little padding: see below). | |
| 142 gtk_widget_set_size_request(body_, kTextWidth + 50, -1); | |
| 143 gtk_widget_set_app_paintable(body_, TRUE); | |
| 144 g_signal_connect(G_OBJECT(body_), "expose-event", | |
| 145 G_CALLBACK(OnExpose), this); | |
| 146 GTK_WIDGET_UNSET_FLAGS(body_, GTK_CAN_FOCUS); | |
| 147 GtkWidget* name_label = gtk_label_new(NULL); | |
| 148 // TODO(estade): This is at best an educated guess, since we don't actually | |
| 149 // use ChromeFont() to draw the text. This is why we need to add so | |
| 150 // much padding when we set the size request. We need to either use ChromeFont | |
| 151 // or somehow extend TextElider. | |
| 152 std::wstring elided_filename = gfx::ElideFilename( | |
| 153 download_model->download()->GetFileName().ToWStringHack(), | |
| 154 ChromeFont(), kTextWidth); | |
| 155 std::string label_markup = | |
| 156 StringPrintf(kLabelColorMarkup, kFilenameColor, | |
| 157 WideToUTF8(elided_filename).c_str()); | |
| 158 gtk_label_set_markup(GTK_LABEL(name_label), label_markup.c_str()); | |
| 159 status_label_ = gtk_label_new(NULL); | |
| 160 // Left align and vertically center the labels. | |
| 161 gtk_misc_set_alignment(GTK_MISC(name_label), 0, 0.5); | |
| 162 gtk_misc_set_alignment(GTK_MISC(status_label_), 0, 0.5); | |
| 163 | 66 |
| 164 // Stack the labels on top of one another. | 67 item = [menu addItemWithTitle:@"Cancel" action:action keyEquivalent:@""]; |
| 165 GtkWidget* text_stack = gtk_vbox_new(FALSE, 0); | 68 [item setTag:CANCEL]; |
| 166 gtk_box_pack_start(GTK_BOX(text_stack), name_label, TRUE, TRUE, 0); | 69 [item setTarget:bridge_]; |
| 167 gtk_box_pack_start(GTK_BOX(text_stack), status_label_, FALSE, FALSE, 0); | |
| 168 gtk_container_add(GTK_CONTAINER(body_), text_stack); | |
| 169 | 70 |
| 170 menu_button_ = gtk_button_new(); | 71 return menu; |
| 171 gtk_widget_set_app_paintable(menu_button_, TRUE); | |
| 172 GTK_WIDGET_UNSET_FLAGS(menu_button_, GTK_CAN_FOCUS); | |
| 173 g_signal_connect(G_OBJECT(menu_button_), "expose-event", | |
| 174 G_CALLBACK(OnExpose), this); | |
| 175 g_signal_connect(G_OBJECT(menu_button_), "button-press-event", | |
| 176 G_CALLBACK(OnMenuButtonPressEvent), this); | |
| 177 g_object_set_data(G_OBJECT(menu_button_), "left-align-popup", | |
| 178 reinterpret_cast<void*>(true)); | |
| 179 gtk_widget_set_size_request(menu_button_, kMenuButtonWidth, 0); | |
| 180 | |
| 181 hbox_ = gtk_hbox_new(FALSE, 0); | |
| 182 gtk_box_pack_start(GTK_BOX(hbox_), body_, FALSE, FALSE, 0); | |
| 183 gtk_box_pack_start(GTK_BOX(hbox_), menu_button_, FALSE, FALSE, 0); | |
| 184 gtk_box_pack_start(GTK_BOX(parent_shelf), hbox_, FALSE, FALSE, 0); | |
| 185 // Insert as the leftmost item. | |
| 186 gtk_box_reorder_child(GTK_BOX(parent_shelf), hbox_, 1); | |
| 187 gtk_widget_show_all(hbox_); | |
| 188 | |
| 189 g_signal_connect(G_OBJECT(parent_shelf_), "size-allocate", | |
| 190 G_CALLBACK(OnShelfResized), this); | |
| 191 | |
| 192 download_model_->download()->AddObserver(this); | |
| 193 } | 72 } |
| 194 | 73 |
| 195 DownloadItemGtk::~DownloadItemGtk() { | 74 |
| 75 // A class for the cocoa side of the download shelf context menu. |
| 76 |
| 77 @interface DownloadShelfContextMenuBridge : NSObject { |
| 78 @private |
| 79 scoped_ptr<DownloadShelfContextMenuMac> contextMenu_; |
| 80 } |
| 81 |
| 82 - (DownloadShelfContextMenuBridge*)initWithModel:(BaseDownloadItemModel*)model; |
| 83 @end |
| 84 |
| 85 @interface DownloadShelfContextMenuBridge(Private) |
| 86 - (void)performAction:(id)sender; |
| 87 - (NSMenu*)menu; |
| 88 @end |
| 89 |
| 90 @implementation DownloadShelfContextMenuBridge |
| 91 |
| 92 - (DownloadShelfContextMenuBridge*)initWithModel:(BaseDownloadItemModel*)model { |
| 93 if ((self = [super init]) == nil) { |
| 94 return nil; |
| 95 } |
| 96 contextMenu_.reset(new DownloadShelfContextMenuMac(model, self)); |
| 97 return self; |
| 98 } |
| 99 |
| 100 @end |
| 101 |
| 102 @implementation DownloadShelfContextMenuBridge(Private) |
| 103 |
| 104 - (void)performAction:(id)sender { |
| 105 contextMenu_->ExecuteItemCommand([sender tag]); |
| 106 } |
| 107 |
| 108 - (NSMenu*)menu { |
| 109 return contextMenu_->GetCocoaMenu(); |
| 110 } |
| 111 |
| 112 @end |
| 113 |
| 114 |
| 115 // DownloadItemMac ------------------------------------------------------------- |
| 116 |
| 117 DownloadItemMac::DownloadItemMac(BaseDownloadItemModel* download_model, |
| 118 NSRect frame, |
| 119 DownloadShelfController* parent) |
| 120 : download_model_(download_model), parent_(parent) { |
| 121 download_model_->download()->AddObserver(this); |
| 122 |
| 123 // TODO(thakis): The windows version of this does all kinds of things |
| 124 // (gratituous use of animation, special handling of dangerous downloads) |
| 125 // that we don't currently do. |
| 126 |
| 127 scoped_nsobject<NSPopUpButton> view( |
| 128 [[NSPopUpButton alloc] initWithFrame:frame pullsDown:YES]); |
| 129 [parent_ addDownloadItem:view.get()]; |
| 130 |
| 131 // TODO(thakis): use filename eliding like gtk/windows versions |
| 132 std::wstring tmpname = |
| 133 download_model->download()->GetFileName().ToWStringHack(); |
| 134 |
| 135 NSString* titleString = base::SysWideToNSString(tmpname); |
| 136 |
| 137 menu_.reset([[DownloadShelfContextMenuBridge alloc] |
| 138 initWithModel:download_model_.get()]); |
| 139 [view.get() setMenu:[menu_.get() menu]]; |
| 140 |
| 141 [view.get() insertItemWithTitle:titleString atIndex:0]; |
| 142 |
| 143 // TODO(thakis): Use file extension and iconForFileType. Currently, this |
| 144 // complains "<filename> is not a full path." |
| 145 [[view.get() itemAtIndex:0] setImage: |
| 146 [[NSWorkspace sharedWorkspace] iconForFile:titleString]]; |
| 147 } |
| 148 |
| 149 DownloadItemMac::~DownloadItemMac() { |
| 196 download_model_->download()->RemoveObserver(this); | 150 download_model_->download()->RemoveObserver(this); |
| 197 } | 151 } |
| 198 | 152 |
| 199 void DownloadItemGtk::OnDownloadUpdated(DownloadItem* download) { | 153 void DownloadItemMac::OnDownloadUpdated(DownloadItem* download) { |
| 200 DCHECK_EQ(download, download_model_->download()); | 154 DCHECK_EQ(download, download_model_->download()); |
| 201 if (!status_label_) { | |
| 202 return; | |
| 203 } | |
| 204 | 155 |
| 205 std::wstring status_text = download_model_->GetStatusText(); | 156 std::wstring status_text = download_model_->GetStatusText(); |
| 206 // Remove the status text label. | 157 // Remove the status text label. |
| 207 if (status_text.empty()) { | 158 if (status_text.empty()) { |
| 208 gtk_widget_destroy(status_label_); | 159 // TODO(thakis): Once there is a status label, hide it here |
| 209 status_label_ = NULL; | |
| 210 return; | 160 return; |
| 211 } | 161 } |
| 212 | 162 |
| 213 std::string label_markup = | 163 // TODO(thakis): Set status_text as status label |
| 214 StringPrintf(kLabelColorMarkup, kStatusColor, | |
| 215 WideToUTF8(status_text).c_str()); | |
| 216 | |
| 217 gtk_label_set_markup(GTK_LABEL(status_label_), label_markup.c_str()); | |
| 218 } | 164 } |
| 219 | |
| 220 // static | |
| 221 void DownloadItemGtk::InitNineBoxes() { | |
| 222 if (body_nine_box_normal_) | |
| 223 return; | |
| 224 | |
| 225 GdkPixbuf* images[9]; | |
| 226 ResourceBundle &rb = ResourceBundle::GetSharedInstance(); | |
| 227 | |
| 228 int i = 0; | |
| 229 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_LEFT_TOP); | |
| 230 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_CENTER_TOP); | |
| 231 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_RIGHT_TOP); | |
| 232 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE); | |
| 233 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE); | |
| 234 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE); | |
| 235 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM); | |
| 236 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM); | |
| 237 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM); | |
| 238 body_nine_box_normal_ = new NineBox(images); | |
| 239 | |
| 240 i = 0; | |
| 241 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_LEFT_TOP_H); | |
| 242 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_CENTER_TOP_H); | |
| 243 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_RIGHT_TOP_H); | |
| 244 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE_H); | |
| 245 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE_H); | |
| 246 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_H); | |
| 247 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM_H); | |
| 248 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM_H); | |
| 249 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_H); | |
| 250 body_nine_box_prelight_ = new NineBox(images); | |
| 251 | |
| 252 i = 0; | |
| 253 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_LEFT_TOP_P); | |
| 254 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_CENTER_TOP_P); | |
| 255 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_RIGHT_TOP_P); | |
| 256 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE_P); | |
| 257 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_CENTER_MIDDLE_P); | |
| 258 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_RIGHT_MIDDLE_P); | |
| 259 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM_P); | |
| 260 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_CENTER_BOTTOM_P); | |
| 261 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_RIGHT_BOTTOM_P); | |
| 262 body_nine_box_active_ = new NineBox(images); | |
| 263 | |
| 264 i = 0; | |
| 265 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_MENU_TOP); | |
| 266 images[i++] = NULL; | |
| 267 images[i++] = NULL; | |
| 268 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_MENU_MIDDLE); | |
| 269 images[i++] = NULL; | |
| 270 images[i++] = NULL; | |
| 271 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_MENU_BOTTOM); | |
| 272 images[i++] = NULL; | |
| 273 images[i++] = NULL; | |
| 274 menu_nine_box_normal_ = new NineBox(images); | |
| 275 | |
| 276 i = 0; | |
| 277 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_MENU_TOP_H); | |
| 278 images[i++] = NULL; | |
| 279 images[i++] = NULL; | |
| 280 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_MENU_MIDDLE_H); | |
| 281 images[i++] = NULL; | |
| 282 images[i++] = NULL; | |
| 283 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_MENU_BOTTOM_H); | |
| 284 images[i++] = NULL; | |
| 285 images[i++] = NULL; | |
| 286 menu_nine_box_prelight_ = new NineBox(images); | |
| 287 | |
| 288 i = 0; | |
| 289 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_MENU_TOP_P); | |
| 290 images[i++] = NULL; | |
| 291 images[i++] = NULL; | |
| 292 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_MENU_MIDDLE_P); | |
| 293 images[i++] = NULL; | |
| 294 images[i++] = NULL; | |
| 295 images[i++] = rb.LoadPixbuf(IDR_DOWNLOAD_BUTTON_MENU_BOTTOM_P); | |
| 296 images[i++] = NULL; | |
| 297 images[i++] = NULL; | |
| 298 menu_nine_box_active_ = new NineBox(images); | |
| 299 } | |
| 300 | |
| 301 // static | |
| 302 gboolean DownloadItemGtk::OnExpose(GtkWidget* widget, GdkEventExpose* e, | |
| 303 DownloadItemGtk* download_item) { | |
| 304 NineBox* nine_box = NULL; | |
| 305 // If true, this widget is |body_|, otherwise it is |menu_button_|. | |
| 306 bool is_body = widget == download_item->body_; | |
| 307 if (GTK_WIDGET_STATE(widget) == GTK_STATE_PRELIGHT) | |
| 308 nine_box = is_body ? body_nine_box_prelight_ : menu_nine_box_prelight_; | |
| 309 else if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE) | |
| 310 nine_box = is_body ? body_nine_box_active_ : menu_nine_box_active_; | |
| 311 else | |
| 312 nine_box = is_body ? body_nine_box_normal_ : menu_nine_box_normal_; | |
| 313 | |
| 314 nine_box->RenderToWidget(widget); | |
| 315 | |
| 316 GtkWidget* child = gtk_bin_get_child(GTK_BIN(widget)); | |
| 317 if (child) | |
| 318 gtk_container_propagate_expose(GTK_CONTAINER(widget), child, e); | |
| 319 | |
| 320 return TRUE; | |
| 321 } | |
| 322 | |
| 323 gboolean DownloadItemGtk::OnMenuButtonPressEvent(GtkWidget* button, | |
| 324 GdkEvent* event, | |
| 325 DownloadItemGtk* item) { | |
| 326 // TODO(port): this never puts the button into the "active" state, | |
| 327 // so this may need to be changed. See note in BrowserToolbarGtk. | |
| 328 if (event->type == GDK_BUTTON_PRESS) { | |
| 329 GdkEventButton* event_button = reinterpret_cast<GdkEventButton*>(event); | |
| 330 if (event_button->button == 1) { | |
| 331 if (item->menu_.get() == NULL) { | |
| 332 item->menu_.reset(new DownloadShelfContextMenuGtk( | |
| 333 item->download_model_.get())); | |
| 334 } | |
| 335 item->menu_->Popup(button, event); | |
| 336 } | |
| 337 } | |
| 338 | |
| 339 return FALSE; | |
| 340 } | |
| 341 | |
| 342 void DownloadItemGtk::OnShelfResized(GtkWidget *widget, | |
| 343 GtkAllocation *allocation, | |
| 344 DownloadItemGtk* item) { | |
| 345 if (item->hbox_->allocation.x + item->hbox_->allocation.width > | |
| 346 item->bounding_widget_->allocation.x) | |
| 347 gtk_widget_hide(item->hbox_); | |
| 348 else | |
| 349 gtk_widget_show(item->hbox_); | |
| 350 } | |
| OLD | NEW |