Fri Nov 24 21:37:01 2006 John Ellis <johne@verizon.net>
[geeqie.git] / src / ui_menu.c
1 /*
2  * (SLIK) SimpLIstic sKin functions
3  * (C) 2004 John Ellis
4  *
5  * Author: John Ellis
6  *
7  * This software is released under the GNU General Public License (GNU GPL).
8  * Please read the included file COPYING for more information.
9  * This software comes with no warranty of any kind, use at your own risk!
10  */
11
12 #ifdef HAVE_CONFIG_H
13 #  include "config.h"
14 #endif
15 #include "intl.h"
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include <gtk/gtk.h>
22
23 #include "ui_menu.h"
24
25
26 /*
27  *-----------------------------------------------------------------------------
28  * menu items
29  *-----------------------------------------------------------------------------
30  */ 
31
32 static void menu_item_finish(GtkWidget *menu, GtkWidget *item, GCallback func, gpointer data)
33 {
34         if (func) g_signal_connect(G_OBJECT(item), "activate", func, data);
35         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
36         gtk_widget_show(item);
37 }
38
39 GtkWidget *menu_item_add(GtkWidget *menu, const gchar *label,
40                          GCallback func, gpointer data)
41 {
42         GtkWidget *item;
43
44         item = gtk_menu_item_new_with_mnemonic(label);
45         menu_item_finish(menu, item, func, data);
46
47         return item;
48 }
49
50 GtkWidget *menu_item_add_stock(GtkWidget *menu, const gchar *label, const gchar *stock_id,
51                                GCallback func, gpointer data)
52 {
53         GtkWidget *item;
54         GtkWidget *image;
55
56         item = gtk_image_menu_item_new_with_mnemonic(label);
57         image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU);
58         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
59         gtk_widget_show(image);
60         menu_item_finish(menu, item, func, data);
61
62         return item;
63 }
64
65 GtkWidget *menu_item_add_sensitive(GtkWidget *menu, const gchar *label, gint sensitive,
66                                    GCallback func, gpointer data)
67 {
68         GtkWidget *item;
69
70         item = menu_item_add(menu, label, func, data);
71         gtk_widget_set_sensitive(item, sensitive);
72
73         return item;
74 }
75
76 GtkWidget *menu_item_add_stock_sensitive(GtkWidget *menu, const gchar *label, const gchar *stock_id, gint sensitive,
77                                          GCallback func, gpointer data)
78 {
79         GtkWidget *item;
80
81         item = menu_item_add_stock(menu, label, stock_id, func, data);
82         gtk_widget_set_sensitive(item, sensitive);
83         
84         return item;
85 }
86
87 GtkWidget *menu_item_add_check(GtkWidget *menu, const gchar *label, gint active,
88                                GCallback func, gpointer data)
89 {
90         GtkWidget *item;
91
92         item = gtk_check_menu_item_new_with_mnemonic(label);
93         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), active);
94         menu_item_finish(menu, item, func, data);
95
96         return item;
97 }
98
99 GtkWidget *menu_item_add_radio(GtkWidget *menu, GtkWidget *parent,
100                                const gchar *label, gint active,
101                                GCallback func, gpointer data)
102 {
103         GtkWidget *item;
104         GSList *group = NULL;
105
106         if (parent) group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(parent));
107
108         item = gtk_radio_menu_item_new_with_mnemonic(group, label);
109         if (active) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), active);
110         menu_item_finish(menu, item, func, data);
111
112         return item;
113 }
114
115 void menu_item_add_divider(GtkWidget *menu)
116 {
117         GtkWidget *item = gtk_menu_item_new();
118         gtk_widget_set_sensitive(item, FALSE);
119         gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
120         gtk_widget_show(item);
121 }
122
123 GtkWidget *menu_item_add_simple(GtkWidget *menu, const gchar *label,
124                                 GCallback func, gpointer data)
125 {
126         GtkWidget *item = gtk_menu_item_new_with_label(label);
127         menu_item_finish(menu, item, func, data);
128
129         return item;
130 }
131
132 /*
133  *-----------------------------------------------------------------------------
134  * popup menus
135  *-----------------------------------------------------------------------------
136  */ 
137
138 static void popup_menu_short_lived_cb(GtkWidget *widget, gpointer data)
139 {
140         /* destroy the menu */
141         g_object_unref(G_OBJECT(data));
142 }
143
144 GtkWidget *popup_menu_short_lived(void)
145 {
146         GtkWidget *menu;
147
148         menu = gtk_menu_new();
149
150         /* take ownership of menu */
151 #ifdef GTK_OBJECT_FLOATING
152         /* GTK+ < 2.10 */
153         g_object_ref(G_OBJECT(menu));
154         gtk_object_sink(GTK_OBJECT(menu));
155 #else
156         /* GTK+ >= 2.10 */
157         g_object_ref_sink(G_OBJECT(menu));
158 #endif
159
160         g_signal_connect(G_OBJECT(menu), "selection_done",
161                          G_CALLBACK(popup_menu_short_lived_cb), menu);
162         return menu;
163 }
164
165 gint popup_menu_position_clamp(GtkMenu *menu, gint *x, gint *y, gint height)
166 {
167         gint adjusted = FALSE;
168         gint w, h;
169         gint xw, xh;
170         
171         w = GTK_WIDGET(menu)->requisition.width;
172         h = GTK_WIDGET(menu)->requisition.height;
173         xw = gdk_screen_width();
174         xh = gdk_screen_height();
175
176         if (*x + w > xw)
177                 {
178                 *x = xw - w;
179                 adjusted = TRUE;
180                 }
181         if (*y + h > xh)
182                 {
183                 if (height)
184                         {
185                         *y = MAX(0, *y - h - height);
186                         }
187                 else
188                         {
189                         *y = xh - h;
190                         }
191                 adjusted = TRUE;
192                 };
193
194         if (*x < 0)
195                 {
196                 *x = 0;
197                 adjusted = TRUE;
198                 }
199         if (*y < 0)
200                 {
201                 *y = 0;
202                 adjusted = TRUE;
203                 }
204
205         return adjusted;
206 }
207