1 /*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2012 Hiroyuki Yamamoto
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
23
24 #include <glib.h>
25 #include <glib/gi18n.h>
26 #include <gtk/gtkwidget.h>
27 #include <gtk/gtkmenu.h>
28 #include <gtk/gtkmenubar.h>
29 #include <gtk/gtkcheckmenuitem.h>
30 #include <gtk/gtkitemfactory.h>
31 #include <gtk/gtkbutton.h>
32 #include <gtk/gtkwindow.h>
33
34 #include "menu.h"
35 #include "utils.h"
36
37 static gchar *menu_translate(const gchar *path, gpointer data);
38
menubar_create(GtkWidget * window,GtkItemFactoryEntry * entries,guint n_entries,const gchar * path,gpointer data)39 GtkWidget *menubar_create(GtkWidget *window, GtkItemFactoryEntry *entries,
40 guint n_entries, const gchar *path, gpointer data)
41 {
42 GtkItemFactory *factory;
43
44 factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, path, NULL);
45 gtk_item_factory_set_translate_func(factory, menu_translate,
46 NULL, NULL);
47 gtk_item_factory_create_items(factory, n_entries, entries, data);
48 gtk_window_add_accel_group(GTK_WINDOW(window), factory->accel_group);
49
50 return gtk_item_factory_get_widget(factory, path);
51 }
52
menu_create_items(GtkItemFactoryEntry * entries,guint n_entries,const gchar * path,GtkItemFactory ** factory,gpointer data)53 GtkWidget *menu_create_items(GtkItemFactoryEntry *entries,
54 guint n_entries, const gchar *path,
55 GtkItemFactory **factory, gpointer data)
56 {
57 *factory = gtk_item_factory_new(GTK_TYPE_MENU, path, NULL);
58 gtk_item_factory_set_translate_func(*factory, menu_translate,
59 NULL, NULL);
60 gtk_item_factory_create_items(*factory, n_entries, entries, data);
61
62 return gtk_item_factory_get_widget(*factory, path);
63 }
64
menu_translate(const gchar * path,gpointer data)65 static gchar *menu_translate(const gchar *path, gpointer data)
66 {
67 gchar *retval;
68
69 retval = gettext(path);
70
71 return retval;
72 }
73
74 #if 0
75 static void factory_print_func(gpointer data, gchar *string)
76 {
77 GString *out_str = data;
78
79 g_string_append(out_str, string);
80 g_string_append_c(out_str, '\n');
81 }
82
83 GString *menu_factory_get_rc(const gchar *path)
84 {
85 GString *string;
86 GtkPatternSpec *pspec;
87 gchar pattern[256];
88
89 pspec = g_new(GtkPatternSpec, 1);
90 g_snprintf(pattern, sizeof(pattern), "%s*", path);
91 gtk_pattern_spec_init(pspec, pattern);
92 string = g_string_new("");
93 gtk_item_factory_dump_items(pspec, FALSE, factory_print_func,
94 string);
95 gtk_pattern_spec_free_segs(pspec);
96
97 return string;
98 }
99
100 void menu_factory_clear_rc(const gchar *rc_str)
101 {
102 GString *string;
103 gchar *p;
104 gchar *start, *end;
105 guint pos = 0;
106
107 string = g_string_new(rc_str);
108 while ((p = strstr(string->str + pos, "(menu-path \"")) != NULL) {
109 pos = p + 12 - string->str;
110 p = strchr(p + 12, '"');
111 if (!p) continue;
112 start = strchr(p + 1, '"');
113 if (!start) continue;
114 end = strchr(start + 1, '"');
115 if (!end) continue;
116 pos = start + 1 - string->str;
117 if (end > start + 1)
118 g_string_erase(string, pos, end - (start + 1));
119 }
120
121 gtk_item_factory_parse_rc_string(string->str);
122 g_string_free(string, TRUE);
123 }
124
125 void menu_factory_copy_rc(const gchar *src_path, const gchar *dest_path)
126 {
127 GString *string;
128 gint src_path_len;
129 gint dest_path_len;
130 gchar *p;
131 guint pos = 0;
132
133 string = menu_factory_get_rc(src_path);
134 src_path_len = strlen(src_path);
135 dest_path_len = strlen(dest_path);
136
137 while ((p = strstr(string->str + pos, src_path)) != NULL) {
138 pos = p - string->str;
139 g_string_erase(string, pos, src_path_len);
140 g_string_insert(string, pos, dest_path);
141 pos += dest_path_len;
142 }
143
144 pos = 0;
145 while ((p = strchr(string->str + pos, ';')) != NULL) {
146 pos = p - string->str;
147 if (pos == 0 || *(p - 1) == '\n')
148 g_string_erase(string, pos, 1);
149 }
150
151 menu_factory_clear_rc(string->str);
152 gtk_item_factory_parse_rc_string(string->str);
153 g_string_free(string, TRUE);
154 }
155 #endif
156
menu_set_sensitive(GtkItemFactory * ifactory,const gchar * path,gboolean sensitive)157 void menu_set_sensitive(GtkItemFactory *ifactory, const gchar *path,
158 gboolean sensitive)
159 {
160 GtkWidget *widget;
161
162 g_return_if_fail(ifactory != NULL);
163
164 widget = gtk_item_factory_get_item(ifactory, path);
165 gtk_widget_set_sensitive(widget, sensitive);
166 }
167
menu_set_sensitive_all(GtkMenuShell * menu_shell,gboolean sensitive)168 void menu_set_sensitive_all(GtkMenuShell *menu_shell, gboolean sensitive)
169 {
170 GList *cur;
171
172 for (cur = menu_shell->children; cur != NULL; cur = cur->next)
173 gtk_widget_set_sensitive(GTK_WIDGET(cur->data), sensitive);
174 }
175
menu_set_active(GtkItemFactory * ifactory,const gchar * path,gboolean is_active)176 void menu_set_active(GtkItemFactory *ifactory, const gchar *path,
177 gboolean is_active)
178 {
179 GtkWidget *widget;
180
181 g_return_if_fail(ifactory != NULL);
182
183 widget = gtk_item_factory_get_item(ifactory, path);
184 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), is_active);
185 }
186
menu_button_position(GtkMenu * menu,gint * x,gint * y,gboolean * push_in,gpointer user_data)187 void menu_button_position(GtkMenu *menu, gint *x, gint *y, gboolean *push_in,
188 gpointer user_data)
189 {
190 GtkWidget *button;
191 GtkRequisition requisition;
192 gint button_xpos, button_ypos;
193 gint xpos, ypos;
194 gint width, height;
195 gint scr_width, scr_height;
196
197 g_return_if_fail(x != NULL && y != NULL && push_in != NULL);
198
199 button = GTK_WIDGET(user_data);
200
201 gtk_widget_get_child_requisition(GTK_WIDGET(menu), &requisition);
202 width = requisition.width;
203 height = requisition.height;
204 gdk_window_get_origin(button->window, &button_xpos, &button_ypos);
205
206 xpos = button_xpos + button->allocation.x;
207 ypos = button_ypos + button->allocation.y + button->allocation.height;
208
209 scr_width = gdk_screen_width();
210 scr_height = gdk_screen_height();
211
212 if (xpos + width > scr_width)
213 xpos -= (xpos + width) - scr_width;
214 if (ypos + height > scr_height)
215 ypos -= button->allocation.height + height;
216 if (xpos < 0)
217 xpos = 0;
218 if (ypos < 0)
219 ypos = 0;
220
221 *x = xpos;
222 *y = ypos;
223 *push_in = FALSE;
224 }
225
menu_widget_position(GtkMenu * menu,gint * x,gint * y,gboolean * push_in,gpointer user_data)226 void menu_widget_position(GtkMenu *menu, gint *x, gint *y, gboolean *push_in,
227 gpointer user_data)
228 {
229 GtkWidget *widget;
230 GtkRequisition requisition;
231 gint w_xpos, w_ypos;
232 gint xpos, ypos;
233 gint width, height;
234 gint scr_width, scr_height;
235
236 g_return_if_fail(x != NULL && y != NULL && push_in != NULL);
237
238 widget = GTK_WIDGET(user_data);
239
240 gtk_widget_get_child_requisition(GTK_WIDGET(menu), &requisition);
241 width = requisition.width;
242 height = requisition.height;
243 gdk_window_get_origin(widget->window, &w_xpos, &w_ypos);
244
245 xpos = w_xpos;
246 ypos = w_ypos;
247
248 scr_width = gdk_screen_width();
249 scr_height = gdk_screen_height();
250
251 if (xpos + width > scr_width)
252 xpos -= (xpos + width) - scr_width;
253 if (ypos + height > scr_height)
254 ypos -= height;
255 if (xpos < 0)
256 xpos = 0;
257 if (ypos < 0)
258 ypos = 0;
259
260 *x = xpos;
261 *y = ypos;
262 *push_in = FALSE;
263 }
264
menu_find_option_menu_index(GtkOptionMenu * optmenu,gpointer data,GCompareFunc func)265 gint menu_find_option_menu_index(GtkOptionMenu *optmenu, gpointer data,
266 GCompareFunc func)
267 {
268 GtkWidget *menu;
269 GtkWidget *menuitem;
270 gpointer menu_data;
271 GList *cur;
272 gint n;
273
274 menu = gtk_option_menu_get_menu(optmenu);
275
276 for (cur = GTK_MENU_SHELL(menu)->children, n = 0;
277 cur != NULL; cur = cur->next, n++) {
278 menuitem = GTK_WIDGET(cur->data);
279 menu_data = g_object_get_data(G_OBJECT(menuitem), MENU_VAL_ID);
280 if (func) {
281 if (func(menu_data, data) == 0)
282 return n;
283 } else if (menu_data == data)
284 return n;
285 }
286
287 return -1;
288 }
289
menu_get_option_menu_active_index(GtkOptionMenu * optmenu)290 gint menu_get_option_menu_active_index(GtkOptionMenu *optmenu)
291 {
292 GtkWidget *menu;
293 GtkWidget *menuitem;
294
295 menu = gtk_option_menu_get_menu(optmenu);
296 menuitem = gtk_menu_get_active(GTK_MENU(menu));
297
298 return GPOINTER_TO_INT
299 (g_object_get_data(G_OBJECT(menuitem), MENU_VAL_ID));
300 }
301