Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Side by Side Diff: chrome/browser/ui/gtk/menu_gtk.cc

Issue 6840068: GTK: Add Recently Closed tabs to the History menu in the global menu bar. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Whitespace nit Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/menu_gtk.h" 5 #include "chrome/browser/ui/gtk/menu_gtk.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/i18n/rtl.h" 9 #include "base/i18n/rtl.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 int alternate_y = y - menu_req->height; 107 int alternate_y = y - menu_req->height;
108 if (widget) 108 if (widget)
109 alternate_y -= widget->allocation.height; 109 alternate_y -= widget->allocation.height;
110 if (menu_bottom >= screen_bottom && alternate_y >= screen_top) 110 if (menu_bottom >= screen_bottom && alternate_y >= screen_top)
111 return alternate_y; 111 return alternate_y;
112 return y; 112 return y;
113 } 113 }
114 114
115 } // namespace 115 } // namespace
116 116
117 GtkWidget* MenuGtk::Delegate::GetDefaultImageForCommandId(int command_id) { 117 GtkWidget* MenuCreator::Delegate::GetDefaultImageForCommandId(int command_id) {
118 const char* stock; 118 const char* stock;
119 switch (command_id) { 119 switch (command_id) {
120 case IDC_NEW_TAB: 120 case IDC_NEW_TAB:
121 case IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB: 121 case IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB:
122 case IDC_CONTENT_CONTEXT_OPENLINKNEWTAB: 122 case IDC_CONTENT_CONTEXT_OPENLINKNEWTAB:
123 case IDC_CONTENT_CONTEXT_OPENAVNEWTAB: 123 case IDC_CONTENT_CONTEXT_OPENAVNEWTAB:
124 stock = GTK_STOCK_NEW; 124 stock = GTK_STOCK_NEW;
125 break; 125 break;
126 126
127 case IDC_CLOSE_TAB: 127 case IDC_CLOSE_TAB:
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 stock = GTK_STOCK_OPEN; 263 stock = GTK_STOCK_OPEN;
264 break; 264 break;
265 265
266 default: 266 default:
267 stock = NULL; 267 stock = NULL;
268 } 268 }
269 269
270 return stock ? gtk_image_new_from_stock(stock, GTK_ICON_SIZE_MENU) : NULL; 270 return stock ? gtk_image_new_from_stock(stock, GTK_ICON_SIZE_MENU) : NULL;
271 } 271 }
272 272
273 GtkWidget* MenuGtk::Delegate::GetImageForCommandId(int command_id) const { 273 GtkWidget* MenuCreator::Delegate::GetImageForCommandId(int command_id) const {
274 return GetDefaultImageForCommandId(command_id); 274 return GetDefaultImageForCommandId(command_id);
275 } 275 }
276 276
277 MenuCreator::MenuCreator(Delegate* delegate)
278 : delegate_(delegate),
279 dummy_accel_group_(gtk_accel_group_new()) {
280 }
281
282 MenuCreator::~MenuCreator() {
283 g_object_unref(dummy_accel_group_);
284 }
285
286 void MenuCreator::BuildSubmenuFromModel(ui::MenuModel* model, GtkWidget* menu) {
287 std::map<int, GtkWidget*> radio_groups;
288 GtkWidget* menu_item = NULL;
289 for (int i = 0; i < model->GetItemCount(); ++i) {
290 SkBitmap icon;
291 std::string label =
292 gfx::ConvertAcceleratorsFromWindowsStyle(
293 UTF16ToUTF8(model->GetLabelAt(i)));
294 bool connect_to_activate = true;
295
296 switch (model->GetTypeAt(i)) {
297 case ui::MenuModel::TYPE_SEPARATOR:
298 menu_item = gtk_separator_menu_item_new();
299 break;
300
301 case ui::MenuModel::TYPE_CHECK:
302 menu_item = gtk_check_menu_item_new_with_mnemonic(label.c_str());
303 break;
304
305 case ui::MenuModel::TYPE_RADIO: {
306 std::map<int, GtkWidget*>::iterator iter =
307 radio_groups.find(model->GetGroupIdAt(i));
308
309 if (iter == radio_groups.end()) {
310 menu_item = gtk_radio_menu_item_new_with_mnemonic(
311 NULL, label.c_str());
312 radio_groups[model->GetGroupIdAt(i)] = menu_item;
313 } else {
314 menu_item = gtk_radio_menu_item_new_with_mnemonic_from_widget(
315 GTK_RADIO_MENU_ITEM(iter->second), label.c_str());
316 }
317 break;
318 }
319 case ui::MenuModel::TYPE_BUTTON_ITEM: {
320 ui::ButtonMenuItemModel* button_menu_item_model =
321 model->GetButtonMenuItemAt(i);
322 menu_item = BuildButtonMenuItem(button_menu_item_model, menu);
323 if (!menu_item)
324 continue;
325 connect_to_activate = false;
326 break;
327 }
328 case ui::MenuModel::TYPE_SUBMENU:
329 case ui::MenuModel::TYPE_COMMAND: {
330 int command_id = model->GetCommandIdAt(i);
331 if (model->GetIconAt(i, &icon))
332 menu_item = BuildMenuItemWithImage(label, icon);
333 else
334 menu_item = BuildMenuItemWithLabel(label, command_id);
335 if (delegate_ && delegate_->AlwaysShowIconForCmd(command_id) &&
336 GTK_IS_IMAGE_MENU_ITEM(menu_item))
337 gtk_util::SetAlwaysShowImage(menu_item);
338 break;
339 }
340
341 default:
342 NOTREACHED();
343 }
344
345 if (model->GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU) {
346 GtkWidget* submenu = gtk_menu_new();
347 BuildSubmenuFromModel(model->GetSubmenuModelAt(i), submenu);
348 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), submenu);
349 }
350
351 ui::AcceleratorGtk accelerator;
352 if (model->GetAcceleratorAt(i, &accelerator)) {
353 gtk_widget_add_accelerator(menu_item,
354 "activate",
355 dummy_accel_group_,
356 accelerator.GetGdkKeyCode(),
357 accelerator.gdk_modifier_type(),
358 GTK_ACCEL_VISIBLE);
359 }
360
361 g_object_set_data(G_OBJECT(menu_item), "model", model);
362 AppendMenuItemToMenu(i, model, menu_item, menu, connect_to_activate);
363
364 menu_item = NULL;
365 }
366 }
367
368 GtkWidget* MenuCreator::BuildMenuItemWithImage(const std::string& label,
369 GtkWidget* image) const {
370 GtkWidget* menu_item =
371 gtk_image_menu_item_new_with_mnemonic(label.c_str());
372 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item), image);
373 return menu_item;
374 }
375
376 GtkWidget* MenuCreator::BuildMenuItemWithImage(const std::string& label,
377 const SkBitmap& icon) const {
378 GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&icon);
379 GtkWidget* menu_item = BuildMenuItemWithImage(label,
380 gtk_image_new_from_pixbuf(pixbuf));
381 g_object_unref(pixbuf);
382 return menu_item;
383 }
384
385 GtkWidget* MenuCreator::BuildMenuItemWithLabel(const std::string& label,
386 int command_id) const {
387 GtkWidget* img =
388 delegate_ ? delegate_->GetImageForCommandId(command_id) :
389 MenuGtk::Delegate::GetDefaultImageForCommandId(command_id);
390 return img ? BuildMenuItemWithImage(label, img) :
391 gtk_menu_item_new_with_mnemonic(label.c_str());
392 }
393
277 MenuGtk::MenuGtk(MenuGtk::Delegate* delegate, 394 MenuGtk::MenuGtk(MenuGtk::Delegate* delegate,
278 ui::MenuModel* model) 395 ui::MenuModel* model)
279 : delegate_(delegate), 396 : MenuCreator(delegate),
397 delegate_(delegate),
280 model_(model), 398 model_(model),
281 dummy_accel_group_(gtk_accel_group_new()),
282 menu_(gtk_custom_menu_new()), 399 menu_(gtk_custom_menu_new()),
283 factory_(this) { 400 factory_(this) {
284 DCHECK(model); 401 DCHECK(model);
285 g_object_ref_sink(menu_); 402 g_object_ref_sink(menu_);
286 ConnectSignalHandlers(); 403 ConnectSignalHandlers();
287 BuildMenuFromModel(); 404 BuildMenuFromModel();
288 } 405 }
289 406
290 MenuGtk::~MenuGtk() { 407 MenuGtk::~MenuGtk() {
291 Cancel(); 408 Cancel();
292 409
293 gtk_widget_destroy(menu_); 410 gtk_widget_destroy(menu_);
294 g_object_unref(menu_); 411 g_object_unref(menu_);
295 412
296 STLDeleteContainerPointers(submenus_we_own_.begin(), submenus_we_own_.end()); 413 STLDeleteContainerPointers(submenus_we_own_.begin(), submenus_we_own_.end());
297 g_object_unref(dummy_accel_group_);
298 } 414 }
299 415
300 void MenuGtk::ConnectSignalHandlers() { 416 void MenuGtk::ConnectSignalHandlers() {
301 // We connect afterwards because OnMenuShow calls SetMenuItemInfo, which may 417 // We connect afterwards because OnMenuShow calls SetMenuItemInfo, which may
302 // take a long time or even start a nested message loop. 418 // take a long time or even start a nested message loop.
303 g_signal_connect(menu_, "show", G_CALLBACK(OnMenuShowThunk), this); 419 g_signal_connect(menu_, "show", G_CALLBACK(OnMenuShowThunk), this);
304 g_signal_connect(menu_, "hide", G_CALLBACK(OnMenuHiddenThunk), this); 420 g_signal_connect(menu_, "hide", G_CALLBACK(OnMenuHiddenThunk), this);
305 } 421 }
306 422
307 GtkWidget* MenuGtk::AppendMenuItemWithLabel(int command_id, 423 GtkWidget* MenuGtk::AppendMenuItemWithLabel(int command_id,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 GTK_IS_IMAGE_MENU_ITEM(menu_item)) 455 GTK_IS_IMAGE_MENU_ITEM(menu_item))
340 gtk_util::SetAlwaysShowImage(menu_item); 456 gtk_util::SetAlwaysShowImage(menu_item);
341 457
342 return AppendMenuItemToMenu(command_id, NULL, menu_item, menu_, true); 458 return AppendMenuItemToMenu(command_id, NULL, menu_item, menu_, true);
343 } 459 }
344 460
345 GtkWidget* MenuGtk::AppendMenuItemToMenu(int index, 461 GtkWidget* MenuGtk::AppendMenuItemToMenu(int index,
346 ui::MenuModel* model, 462 ui::MenuModel* model,
347 GtkWidget* menu_item, 463 GtkWidget* menu_item,
348 GtkWidget* menu, 464 GtkWidget* menu,
349 bool connect_to_activate) { 465 bool connect_to_activate) {
Evan Stade 2011/04/20 22:52:10 this doesn't need to be passed here; check model->
350 SetMenuItemID(menu_item, index); 466 SetMenuItemID(menu_item, index);
351 467
352 // Native menu items do their own thing, so only selectively listen for the 468 // Native menu items do their own thing, so only selectively listen for the
353 // activate signal. 469 // activate signal.
354 if (connect_to_activate) { 470 if (connect_to_activate) {
355 g_signal_connect(menu_item, "activate", 471 g_signal_connect(menu_item, "activate",
356 G_CALLBACK(OnMenuItemActivatedThunk), this); 472 G_CALLBACK(OnMenuItemActivatedThunk), this);
357 } 473 }
358 474
359 // AppendMenuItemToMenu is used both internally when we control menu creation 475 // AppendMenuItemToMenu is used both internally when we control menu creation
360 // from a model (where the model can choose to hide certain menu items), and 476 // from a model (where the model can choose to hide certain menu items), and
361 // with immediate commands which don't provide the option. 477 // with immediate commands which don't provide the option.
362 if (model) { 478 if (model) {
363 if (model->IsVisibleAt(index)) 479 if (model->IsVisibleAt(index))
364 gtk_widget_show(menu_item); 480 gtk_widget_show(menu_item);
365 } else { 481 } else {
366 gtk_widget_show(menu_item); 482 gtk_widget_show(menu_item);
367 } 483 }
368 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); 484 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
Evan Stade 2011/04/20 22:52:10 is it necessary to do this here? why not do this i
369 return menu_item; 485 return menu_item;
370 } 486 }
371 487
372 void MenuGtk::PopupForWidget(GtkWidget* widget, int button, 488 void MenuGtk::PopupForWidget(GtkWidget* widget, int button,
373 guint32 event_time) { 489 guint32 event_time) {
374 gtk_menu_popup(GTK_MENU(menu_), NULL, NULL, 490 gtk_menu_popup(GTK_MENU(menu_), NULL, NULL,
375 WidgetMenuPositionFunc, 491 WidgetMenuPositionFunc,
376 widget, 492 widget,
377 button, event_time); 493 button, event_time);
378 } 494 }
(...skipping 18 matching lines...) Expand all
397 } 513 }
398 514
399 void MenuGtk::Cancel() { 515 void MenuGtk::Cancel() {
400 gtk_menu_popdown(GTK_MENU(menu_)); 516 gtk_menu_popdown(GTK_MENU(menu_));
401 } 517 }
402 518
403 void MenuGtk::UpdateMenu() { 519 void MenuGtk::UpdateMenu() {
404 gtk_container_foreach(GTK_CONTAINER(menu_), SetMenuItemInfo, this); 520 gtk_container_foreach(GTK_CONTAINER(menu_), SetMenuItemInfo, this);
405 } 521 }
406 522
407 GtkWidget* MenuGtk::BuildMenuItemWithImage(const std::string& label,
408 GtkWidget* image) {
409 GtkWidget* menu_item =
410 gtk_image_menu_item_new_with_mnemonic(label.c_str());
411 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item), image);
412 return menu_item;
413 }
414
415 GtkWidget* MenuGtk::BuildMenuItemWithImage(const std::string& label,
416 const SkBitmap& icon) {
417 GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&icon);
418 GtkWidget* menu_item = BuildMenuItemWithImage(label,
419 gtk_image_new_from_pixbuf(pixbuf));
420 g_object_unref(pixbuf);
421 return menu_item;
422 }
423
424 GtkWidget* MenuGtk::BuildMenuItemWithLabel(const std::string& label,
425 int command_id) {
426 GtkWidget* img =
427 delegate_ ? delegate_->GetImageForCommandId(command_id) :
428 MenuGtk::Delegate::GetDefaultImageForCommandId(command_id);
429 return img ? BuildMenuItemWithImage(label, img) :
430 gtk_menu_item_new_with_mnemonic(label.c_str());
431 }
432
433 void MenuGtk::BuildMenuFromModel() { 523 void MenuGtk::BuildMenuFromModel() {
434 BuildSubmenuFromModel(model_, menu_); 524 BuildSubmenuFromModel(model_, menu_);
435 } 525 }
436 526
437 void MenuGtk::BuildSubmenuFromModel(ui::MenuModel* model, GtkWidget* menu) {
438 std::map<int, GtkWidget*> radio_groups;
439 GtkWidget* menu_item = NULL;
440 for (int i = 0; i < model->GetItemCount(); ++i) {
441 SkBitmap icon;
442 std::string label =
443 gfx::ConvertAcceleratorsFromWindowsStyle(
444 UTF16ToUTF8(model->GetLabelAt(i)));
445 bool connect_to_activate = true;
446
447 switch (model->GetTypeAt(i)) {
448 case ui::MenuModel::TYPE_SEPARATOR:
449 menu_item = gtk_separator_menu_item_new();
450 break;
451
452 case ui::MenuModel::TYPE_CHECK:
453 menu_item = gtk_check_menu_item_new_with_mnemonic(label.c_str());
454 break;
455
456 case ui::MenuModel::TYPE_RADIO: {
457 std::map<int, GtkWidget*>::iterator iter =
458 radio_groups.find(model->GetGroupIdAt(i));
459
460 if (iter == radio_groups.end()) {
461 menu_item = gtk_radio_menu_item_new_with_mnemonic(
462 NULL, label.c_str());
463 radio_groups[model->GetGroupIdAt(i)] = menu_item;
464 } else {
465 menu_item = gtk_radio_menu_item_new_with_mnemonic_from_widget(
466 GTK_RADIO_MENU_ITEM(iter->second), label.c_str());
467 }
468 break;
469 }
470 case ui::MenuModel::TYPE_BUTTON_ITEM: {
471 ui::ButtonMenuItemModel* button_menu_item_model =
472 model->GetButtonMenuItemAt(i);
473 menu_item = BuildButtonMenuItem(button_menu_item_model, menu);
474 connect_to_activate = false;
475 break;
476 }
477 case ui::MenuModel::TYPE_SUBMENU:
478 case ui::MenuModel::TYPE_COMMAND: {
479 int command_id = model->GetCommandIdAt(i);
480 if (model->GetIconAt(i, &icon))
481 menu_item = BuildMenuItemWithImage(label, icon);
482 else
483 menu_item = BuildMenuItemWithLabel(label, command_id);
484 if (delegate_ && delegate_->AlwaysShowIconForCmd(command_id) &&
485 GTK_IS_IMAGE_MENU_ITEM(menu_item))
486 gtk_util::SetAlwaysShowImage(menu_item);
487 break;
488 }
489
490 default:
491 NOTREACHED();
492 }
493
494 if (model->GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU) {
495 GtkWidget* submenu = gtk_menu_new();
496 BuildSubmenuFromModel(model->GetSubmenuModelAt(i), submenu);
497 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), submenu);
498 }
499
500 ui::AcceleratorGtk accelerator;
501 if (model->GetAcceleratorAt(i, &accelerator)) {
502 gtk_widget_add_accelerator(menu_item,
503 "activate",
504 dummy_accel_group_,
505 accelerator.GetGdkKeyCode(),
506 accelerator.gdk_modifier_type(),
507 GTK_ACCEL_VISIBLE);
508 }
509
510 g_object_set_data(G_OBJECT(menu_item), "model", model);
511 AppendMenuItemToMenu(i, model, menu_item, menu, connect_to_activate);
512
513 menu_item = NULL;
514 }
515 }
516
517 GtkWidget* MenuGtk::BuildButtonMenuItem(ui::ButtonMenuItemModel* model, 527 GtkWidget* MenuGtk::BuildButtonMenuItem(ui::ButtonMenuItemModel* model,
518 GtkWidget* menu) { 528 GtkWidget* menu) {
519 GtkWidget* menu_item = gtk_custom_menu_item_new( 529 GtkWidget* menu_item = gtk_custom_menu_item_new(
520 gfx::RemoveWindowsStyleAccelerators(UTF16ToUTF8(model->label())).c_str()); 530 gfx::RemoveWindowsStyleAccelerators(UTF16ToUTF8(model->label())).c_str());
521 531
522 // Set up the callback to the model for when it is clicked. 532 // Set up the callback to the model for when it is clicked.
523 g_object_set_data(G_OBJECT(menu_item), "button-model", model); 533 g_object_set_data(G_OBJECT(menu_item), "button-model", model);
524 g_signal_connect(menu_item, "button-pushed", 534 g_signal_connect(menu_item, "button-pushed",
525 G_CALLBACK(OnMenuButtonPressedThunk), this); 535 G_CALLBACK(OnMenuButtonPressedThunk), this);
526 g_signal_connect(menu_item, "try-button-pushed", 536 g_signal_connect(menu_item, "try-button-pushed",
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 gtk_widget_hide(widget); 833 gtk_widget_hide(widget);
824 } 834 }
825 835
826 GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget)); 836 GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget));
827 if (submenu) { 837 if (submenu) {
828 gtk_container_foreach(GTK_CONTAINER(submenu), &SetMenuItemInfo, 838 gtk_container_foreach(GTK_CONTAINER(submenu), &SetMenuItemInfo,
829 userdata); 839 userdata);
830 } 840 }
831 } 841 }
832 } 842 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698