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

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

Issue 20245: Port the Menu class to GTK. (Closed)
Patch Set: Fixes for evanm Created 11 years, 10 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/gtk/menu_gtk.h"
6
7 #include "base/logging.h"
8 #include "base/string_util.h"
9 #include "chrome/common/l10n_util.h"
10
11 MenuGtk::MenuGtk(MenuGtk::Delegate* delegate,
12 const MenuCreateMaterial* menu_data)
13 : delegate_(delegate),
14 menu_(gtk_menu_new()) {
15 BuildMenuIn(menu_, menu_data);
16 }
17
18 MenuGtk::~MenuGtk() {
19 g_object_unref(menu_);
20 }
21
22 void MenuGtk::Popup(GtkWidget* widget, GdkEvent* event) {
23 DCHECK(event->type == GDK_BUTTON_PRESS)
24 << "Non-button press event sent to RunMenuAt";
25
26 gtk_container_foreach(GTK_CONTAINER(menu_), SetMenuItemInfo, this);
27
28 GdkEventButton* event_button = reinterpret_cast<GdkEventButton*>(event);
29 gtk_menu_popup(GTK_MENU(menu_), NULL, NULL,
30 MenuPositionFunc,
31 widget,
32 event_button->button, event_button->time);
33 }
34
35 void MenuGtk::BuildMenuIn(GtkWidget* menu,
36 const MenuCreateMaterial* menu_data) {
37 for (; menu_data->type != MENU_END; menu_data++) {
38 GtkWidget* menu_item = NULL;
39
40 std::wstring label;
41 if (menu_data->label_argument) {
42 label = l10n_util::GetStringF(
43 menu_data->label_id,
44 l10n_util::GetString(menu_data->label_argument));
45 } else if (menu_data->label_id) {
46 label = l10n_util::GetString(menu_data->label_id);
47 } else {
48 DCHECK(menu_data->type == MENU_SEPARATOR) << "Menu definition broken";
49 }
50
51 switch (menu_data->type) {
52 case MENU_CHECKBOX:
53 menu_item = gtk_check_menu_item_new_with_label(
54 WideToUTF8(label).c_str());
55 break;
56 case MENU_SEPARATOR:
57 menu_item = gtk_separator_menu_item_new();
58 break;
59 case MENU_NORMAL:
60 default:
61 menu_item = gtk_menu_item_new_with_label(WideToUTF8(label).c_str());
62 break;
63 }
64
65 if (menu_data->submenu) {
66 GtkWidget* submenu = gtk_menu_new();
67 BuildMenuIn(submenu, menu_data->submenu);
68 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), submenu);
69 }
70
71 g_object_set_data(G_OBJECT(menu_item), "menu-data",
72 const_cast<MenuCreateMaterial*>(menu_data));
73
74 g_signal_connect(G_OBJECT(menu_item), "activate",
75 G_CALLBACK(OnMenuItemActivated), this);
76
77 gtk_widget_show(menu_item);
78 gtk_menu_append(menu, menu_item);
79 }
80 }
81
82 /* static */
83 void MenuGtk::OnMenuItemActivated(GtkMenuItem* menuitem, MenuGtk* menu) {
84 // We receive activation messages when highlighting a menu that has a
85 // submenu. Ignore them.
86 if (!gtk_menu_item_get_submenu(menuitem)) {
87 const MenuCreateMaterial* data =
88 reinterpret_cast<const MenuCreateMaterial*>(
89 g_object_get_data(G_OBJECT(menuitem), "menu-data"));
90 menu->delegate_->ExecuteCommand(data->id);
91 }
92 }
93
94 /* static */
Dean McNamee 2009/02/18 12:35:17 I've seen this in a few places now. I don't think
95 void MenuGtk::MenuPositionFunc(GtkMenu* menu,
96 int* x,
97 int* y,
98 gboolean* push_in,
99 void* void_widget) {
100 GtkWidget* widget = GTK_WIDGET(void_widget);
101 GtkRequisition menu_req;
102 GdkRectangle monitor;
103
104 gtk_widget_size_request(GTK_WIDGET(menu), &menu_req);
105
106 GdkScreen* screen = gtk_widget_get_screen(GTK_WIDGET(menu));
107 gint monitor_num = gdk_screen_get_monitor_at_window(screen, widget->window);
108 if (monitor_num < 0)
109 monitor_num = 0;
110 gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor);
111
112 gdk_window_get_origin(widget->window, x, y);
113 *x += widget->allocation.x + widget->allocation.width;
114 *y += widget->allocation.y + widget->allocation.height;
115
116 *x -= menu_req.width;
117
118 // TODO(erg): Deal with this scrolling off the bottom of the screen.
119
120 // Regretfully, we can't rely on push_in to alter the coordinates above to
121 // always make the menu fit on screen. It'd make the above calculations just
122 // work though...
123 *push_in = FALSE;
124 }
125
126 /* static */
127 void MenuGtk::SetMenuItemInfo(GtkWidget* widget, void* raw_menu) {
128 MenuGtk* menu = static_cast<MenuGtk*>(raw_menu);
129 const MenuCreateMaterial* data =
130 reinterpret_cast<const MenuCreateMaterial*>(
131 g_object_get_data(G_OBJECT(widget), "menu-data"));
132
133 if (data) {
134 if (GTK_IS_CHECK_MENU_ITEM(widget)) {
135 GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM(widget);
136 gtk_check_menu_item_set_active(
137 item, menu->delegate_->IsItemChecked(data->id));
138 }
139
140 if (GTK_IS_MENU_ITEM(widget)) {
141 gtk_widget_set_sensitive(
142 widget, menu->delegate_->IsCommandEnabled(data->id));
143
144 GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget));
145 if (submenu) {
146 gtk_container_foreach(GTK_CONTAINER(submenu), &MenuGtk::SetMenuItemInfo,
147 raw_menu);
148 }
149 }
150 }
151 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698