Simplify vflist_get_formatted()
[geeqie.git] / src / ui_menu.c
1 /*
2  * Copyright (C) 2004 John Ellis
3  * Copyright (C) 2008 - 2016 The Geeqie Team
4  *
5  * Author: John Ellis
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #endif
25 #include "intl.h"
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <gtk/gtk.h>
32
33 #include "ui_menu.h"
34
35
36 /*
37  *-----------------------------------------------------------------------------
38  * menu items
39  *-----------------------------------------------------------------------------
40  */
41
42 static void menu_item_finish(GtkWidget *menu, GtkWidget *item, GCallback func, gpointer data)
43 {
44         if (func) g_signal_connect(G_OBJECT(item), "activate", func, data);
45         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
46         gtk_widget_show(item);
47 }
48
49 GtkWidget *menu_item_add(GtkWidget *menu, const gchar *label,
50                          GCallback func, gpointer data)
51 {
52         GtkWidget *item;
53
54         item = gtk_menu_item_new_with_mnemonic(label);
55         menu_item_finish(menu, item, func, data);
56
57         return item;
58 }
59
60 GtkWidget *menu_item_add_stock(GtkWidget *menu, const gchar *label, const gchar *stock_id,
61                                GCallback func, gpointer data)
62 {
63         GtkWidget *item;
64         GtkWidget *image;
65
66         item = gtk_image_menu_item_new_with_mnemonic(label);
67         image = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_MENU);
68         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
69         gtk_widget_show(image);
70         menu_item_finish(menu, item, func, data);
71
72         return item;
73 }
74
75 GtkWidget *menu_item_add_sensitive(GtkWidget *menu, const gchar *label, gboolean sensitive,
76                                    GCallback func, gpointer data)
77 {
78         GtkWidget *item;
79
80         item = menu_item_add(menu, label, func, data);
81         gtk_widget_set_sensitive(item, sensitive);
82
83         return item;
84 }
85
86 GtkWidget *menu_item_add_stock_sensitive(GtkWidget *menu, const gchar *label, const gchar *stock_id, gboolean sensitive,
87                                          GCallback func, gpointer data)
88 {
89         GtkWidget *item;
90
91         item = menu_item_add_stock(menu, label, stock_id, func, data);
92         gtk_widget_set_sensitive(item, sensitive);
93
94         return item;
95 }
96
97 GtkWidget *menu_item_add_check(GtkWidget *menu, const gchar *label, gboolean active,
98                                GCallback func, gpointer data)
99 {
100         GtkWidget *item;
101
102         item = gtk_check_menu_item_new_with_mnemonic(label);
103         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), active);
104         menu_item_finish(menu, item, func, data);
105
106         return item;
107 }
108
109 GtkWidget *menu_item_add_radio(GtkWidget *menu, const gchar *label, gpointer item_data, gboolean active,
110                                GCallback func, gpointer data)
111 {
112         GtkWidget *item = menu_item_add_check(menu, label, active, func, data);
113         g_object_set_data(G_OBJECT(item), "menu_item_radio_data", item_data);
114         g_object_set(G_OBJECT(item), "draw-as-radio", TRUE, NULL);
115
116         return item;
117 }
118
119 void menu_item_add_divider(GtkWidget *menu)
120 {
121         GtkWidget *item = gtk_separator_menu_item_new();
122         gtk_widget_set_sensitive(item, FALSE);
123         gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
124         gtk_widget_show(item);
125 }
126
127 GtkWidget *menu_item_add_simple(GtkWidget *menu, const gchar *label,
128                                 GCallback func, gpointer data)
129 {
130         GtkWidget *item = gtk_menu_item_new_with_label(label);
131         menu_item_finish(menu, item, func, data);
132
133         return item;
134 }
135
136 /*
137  *-----------------------------------------------------------------------------
138  * popup menus
139  *-----------------------------------------------------------------------------
140  */
141
142 static void popup_menu_short_lived_cb(GtkWidget *widget, gpointer data)
143 {
144         /* destroy the menu */
145         g_object_unref(G_OBJECT(data));
146 }
147
148 GtkWidget *popup_menu_short_lived(void)
149 {
150         GtkWidget *menu;
151
152         menu = gtk_menu_new();
153
154         /* take ownership of menu */
155 #ifdef GTK_OBJECT_FLOATING
156         /* GTK+ < 2.10 */
157         g_object_ref(G_OBJECT(menu));
158         gtk_object_sink(GTK_OBJECT(menu));
159 #else
160         /* GTK+ >= 2.10 */
161         g_object_ref_sink(G_OBJECT(menu));
162 #endif
163
164         g_signal_connect(G_OBJECT(menu), "selection_done",
165                          G_CALLBACK(popup_menu_short_lived_cb), menu);
166         return menu;
167 }
168
169 gboolean popup_menu_position_clamp(GtkMenu *menu, gint *x, gint *y, gint height)
170 {
171         gboolean adjusted = FALSE;
172         gint w, h;
173         gint xw, xh;
174         GtkRequisition requisition;
175
176         gtk_widget_get_requisition(GTK_WIDGET(menu), &requisition);
177         w = requisition.width;
178         h = requisition.height;
179         xw = gdk_screen_width();
180         xh = gdk_screen_height();
181
182         if (*x + w > xw)
183                 {
184                 *x = xw - w;
185                 adjusted = TRUE;
186                 }
187         if (*y + h > xh)
188                 {
189                 if (height)
190                         {
191                         *y = MAX(0, *y - h - height);
192                         }
193                 else
194                         {
195                         *y = xh - h;
196                         }
197                 adjusted = TRUE;
198                 };
199
200         if (*x < 0)
201                 {
202                 *x = 0;
203                 adjusted = TRUE;
204                 }
205         if (*y < 0)
206                 {
207                 *y = 0;
208                 adjusted = TRUE;
209                 }
210
211         return adjusted;
212 }
213 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */