]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/gtkutil/menu.cpp
fix invalid use of <glib/...> headers
[xonotic/netradiant.git] / libs / gtkutil / menu.cpp
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant 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    GtkRadiant 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
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "menu.h"
23
24 #include <ctype.h>
25 #include <gtk/gtkmenu.h>
26 #include <gtk/gtkmenubar.h>
27 #include <gtk/gtkradiomenuitem.h>
28 #include <gtk/gtktearoffmenuitem.h>
29 #include <gtk/gtkaccellabel.h>
30
31 #include "generic/callback.h"
32
33 #include "accelerator.h"
34 #include "closure.h"
35 #include "container.h"
36 #include "pointer.h"
37
38 void menu_add_item( GtkMenu* menu, GtkMenuItem* item ){
39         gtk_container_add( GTK_CONTAINER( menu ), GTK_WIDGET( item ) );
40 }
41
42 GtkMenuItem* menu_separator( GtkMenu* menu ){
43         GtkMenuItem* menu_item = GTK_MENU_ITEM( gtk_menu_item_new() );
44         container_add_widget( GTK_CONTAINER( menu ), GTK_WIDGET( menu_item ) );
45         gtk_widget_set_sensitive( GTK_WIDGET( menu_item ), FALSE );
46         gtk_widget_show( GTK_WIDGET( menu_item ) );
47         return menu_item;
48 }
49
50 GtkTearoffMenuItem* menu_tearoff( GtkMenu* menu ){
51         GtkTearoffMenuItem* menu_item = GTK_TEAROFF_MENU_ITEM( gtk_tearoff_menu_item_new() );
52         container_add_widget( GTK_CONTAINER( menu ), GTK_WIDGET( menu_item ) );
53 // gtk_widget_set_sensitive(GTK_WIDGET(menu_item), FALSE); -- controls whether menu is detachable
54         gtk_widget_show( GTK_WIDGET( menu_item ) );
55         return menu_item;
56 }
57
58 GtkMenuItem* new_sub_menu_item_with_mnemonic( const char* mnemonic ){
59         GtkMenuItem* item = GTK_MENU_ITEM( gtk_menu_item_new_with_mnemonic( mnemonic ) );
60         gtk_widget_show( GTK_WIDGET( item ) );
61
62         GtkWidget* sub_menu = gtk_menu_new();
63         gtk_menu_item_set_submenu( item, sub_menu );
64
65         return item;
66 }
67
68 GtkMenu* create_sub_menu_with_mnemonic( GtkMenuShell* parent, const char* mnemonic ){
69         GtkMenuItem* item = new_sub_menu_item_with_mnemonic( mnemonic );
70         container_add_widget( GTK_CONTAINER( parent ), GTK_WIDGET( item ) );
71         return GTK_MENU( gtk_menu_item_get_submenu( item ) );
72 }
73
74 GtkMenu* create_sub_menu_with_mnemonic( GtkMenuBar* bar, const char* mnemonic ){
75         return create_sub_menu_with_mnemonic( GTK_MENU_SHELL( bar ), mnemonic );
76 }
77
78 GtkMenu* create_sub_menu_with_mnemonic( GtkMenu* parent, const char* mnemonic ){
79         return create_sub_menu_with_mnemonic( GTK_MENU_SHELL( parent ), mnemonic );
80 }
81
82 void activate_closure_callback( GtkWidget* widget, gpointer data ){
83         ( *reinterpret_cast<Callback*>( data ) )( );
84 }
85
86 guint menu_item_connect_callback( GtkMenuItem* item, const Callback& callback ){
87 #if 1
88         return g_signal_connect_swapped( G_OBJECT( item ), "activate", G_CALLBACK( callback.getThunk() ), callback.getEnvironment() );
89 #else
90         return g_signal_connect_closure( G_OBJECT( item ), "activate", create_cclosure( G_CALLBACK( activate_closure_callback ), callback ), FALSE );
91 #endif
92 }
93
94 guint check_menu_item_connect_callback( GtkCheckMenuItem* item, const Callback& callback ){
95 #if 1
96         guint handler = g_signal_connect_swapped( G_OBJECT( item ), "toggled", G_CALLBACK( callback.getThunk() ), callback.getEnvironment() );
97 #else
98         guint handler = g_signal_connect_closure( G_OBJECT( item ), "toggled", create_cclosure( G_CALLBACK( activate_closure_callback ), callback ), TRUE );
99 #endif
100         g_object_set_data( G_OBJECT( item ), "handler", gint_to_pointer( handler ) );
101         return handler;
102 }
103
104 GtkMenuItem* new_menu_item_with_mnemonic( const char *mnemonic, const Callback& callback ){
105         GtkMenuItem* item = GTK_MENU_ITEM( gtk_menu_item_new_with_mnemonic( mnemonic ) );
106         gtk_widget_show( GTK_WIDGET( item ) );
107         menu_item_connect_callback( item, callback );
108         return item;
109 }
110
111 GtkMenuItem* create_menu_item_with_mnemonic( GtkMenu* menu, const char *mnemonic, const Callback& callback ){
112         GtkMenuItem* item = new_menu_item_with_mnemonic( mnemonic, callback );
113         container_add_widget( GTK_CONTAINER( menu ), GTK_WIDGET( item ) );
114         return item;
115 }
116
117 GtkCheckMenuItem* new_check_menu_item_with_mnemonic( const char* mnemonic, const Callback& callback ){
118         GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM( gtk_check_menu_item_new_with_mnemonic( mnemonic ) );
119         gtk_widget_show( GTK_WIDGET( item ) );
120         check_menu_item_connect_callback( item, callback );
121         return item;
122 }
123
124 GtkCheckMenuItem* create_check_menu_item_with_mnemonic( GtkMenu* menu, const char* mnemonic, const Callback& callback ){
125         GtkCheckMenuItem* item = new_check_menu_item_with_mnemonic( mnemonic, callback );
126         container_add_widget( GTK_CONTAINER( menu ), GTK_WIDGET( item ) );
127         return item;
128 }
129
130 GtkRadioMenuItem* new_radio_menu_item_with_mnemonic( GSList** group, const char* mnemonic, const Callback& callback ){
131         GtkRadioMenuItem* item = GTK_RADIO_MENU_ITEM( gtk_radio_menu_item_new_with_mnemonic( *group, mnemonic ) );
132         if ( *group == 0 ) {
133                 gtk_check_menu_item_set_state( GTK_CHECK_MENU_ITEM( item ), TRUE );
134         }
135         *group = gtk_radio_menu_item_group( item );
136         gtk_widget_show( GTK_WIDGET( item ) );
137         check_menu_item_connect_callback( GTK_CHECK_MENU_ITEM( item ), callback );
138         return item;
139 }
140
141 GtkRadioMenuItem* create_radio_menu_item_with_mnemonic( GtkMenu* menu, GSList** group, const char* mnemonic, const Callback& callback ){
142         GtkRadioMenuItem* item = new_radio_menu_item_with_mnemonic( group, mnemonic, callback );
143         container_add_widget( GTK_CONTAINER( menu ), GTK_WIDGET( item ) );
144         return item;
145 }
146
147 void check_menu_item_set_active_no_signal( GtkCheckMenuItem* item, gboolean active ){
148         guint handler_id = gpointer_to_int( g_object_get_data( G_OBJECT( item ), "handler" ) );
149         g_signal_handler_block( G_OBJECT( item ), handler_id );
150         gtk_check_menu_item_set_active( item, active );
151         g_signal_handler_unblock( G_OBJECT( item ), handler_id );
152 }
153
154
155
156 void radio_menu_item_set_active_no_signal( GtkRadioMenuItem* item, gboolean active ){
157         {
158                 for ( GSList* l = gtk_radio_menu_item_get_group( item ); l != 0; l = g_slist_next( l ) )
159                 {
160                         g_signal_handler_block( G_OBJECT( l->data ), gpointer_to_int( g_object_get_data( G_OBJECT( l->data ), "handler" ) ) );
161                 }
162         }
163         gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( item ), active );
164         {
165                 for ( GSList* l = gtk_radio_menu_item_get_group( item ); l != 0; l = g_slist_next( l ) )
166                 {
167                         g_signal_handler_unblock( G_OBJECT( l->data ), gpointer_to_int( g_object_get_data( G_OBJECT( l->data ), "handler" ) ) );
168                 }
169         }
170 }
171
172
173 void menu_item_set_accelerator( GtkMenuItem* item, GClosure* closure ){
174         GtkAccelLabel* accel_label = GTK_ACCEL_LABEL( gtk_bin_get_child( GTK_BIN( item ) ) );
175         gtk_accel_label_set_accel_closure( accel_label, closure );
176 }
177
178 void accelerator_name( const Accelerator& accelerator, GString* gstring ){
179         gboolean had_mod = FALSE;
180         if ( accelerator.modifiers & GDK_SHIFT_MASK ) {
181                 g_string_append( gstring, "Shift" );
182                 had_mod = TRUE;
183         }
184         if ( accelerator.modifiers & GDK_CONTROL_MASK ) {
185                 if ( had_mod ) {
186                         g_string_append( gstring, "+" );
187                 }
188                 g_string_append( gstring, "Ctrl" );
189                 had_mod = TRUE;
190         }
191         if ( accelerator.modifiers & GDK_MOD1_MASK ) {
192                 if ( had_mod ) {
193                         g_string_append( gstring, "+" );
194                 }
195                 g_string_append( gstring, "Alt" );
196                 had_mod = TRUE;
197         }
198
199         if ( had_mod ) {
200                 g_string_append( gstring, "+" );
201         }
202         if ( accelerator.key < 0x80 || ( accelerator.key > 0x80 && accelerator.key <= 0xff ) ) {
203                 switch ( accelerator.key )
204                 {
205                 case ' ':
206                         g_string_append( gstring, "Space" );
207                         break;
208                 case '\\':
209                         g_string_append( gstring, "Backslash" );
210                         break;
211                 default:
212                         g_string_append_c( gstring, gchar( toupper( accelerator.key ) ) );
213                         break;
214                 }
215         }
216         else
217         {
218                 gchar *tmp;
219
220                 tmp = gtk_accelerator_name( accelerator.key, (GdkModifierType)0 );
221                 if ( tmp[0] != 0 && tmp[1] == 0 ) {
222                         tmp[0] = gchar( toupper( tmp[0] ) );
223                 }
224                 g_string_append( gstring, tmp );
225                 g_free( tmp );
226         }
227 }
228
229 void menu_item_set_accelerator( GtkMenuItem* item, Accelerator accelerator ){
230         GtkAccelLabel* accel_label = GTK_ACCEL_LABEL( gtk_bin_get_child( GTK_BIN( item ) ) );
231
232         g_free( accel_label->accel_string );
233         accel_label->accel_string = 0;
234
235         GString* gstring = g_string_new( accel_label->accel_string );
236         g_string_append( gstring, "   " );
237
238         accelerator_name( accelerator, gstring );
239
240         g_free( accel_label->accel_string );
241         accel_label->accel_string = gstring->str;
242         g_string_free( gstring, FALSE );
243
244         if ( !accel_label->accel_string ) {
245                 accel_label->accel_string = g_strdup( "" );
246         }
247
248         gtk_widget_queue_resize( GTK_WIDGET( accel_label ) );
249 }
250
251 void menu_item_add_accelerator( GtkMenuItem* item, Accelerator accelerator ){
252         if ( accelerator.key != 0 ) {
253                 GClosure* closure = global_accel_group_find( accelerator );
254                 if ( closure != 0 ) {
255                         menu_item_set_accelerator( item, closure );
256                 }
257                 else
258                 {
259                         menu_item_set_accelerator( item, accelerator );
260                 }
261         }
262 }
263
264 GtkMenuItem* create_menu_item_with_mnemonic( GtkMenu* menu, const char* mnemonic, const Command& command ){
265         GtkMenuItem* item = create_menu_item_with_mnemonic( menu, mnemonic, command.m_callback );
266         menu_item_add_accelerator( item, command.m_accelerator );
267         return item;
268 }
269
270 void check_menu_item_set_active_callback( GtkCheckMenuItem& item, bool enabled ){
271         check_menu_item_set_active_no_signal( &item, enabled );
272 }
273 typedef ReferenceCaller1<GtkCheckMenuItem, bool, check_menu_item_set_active_callback> CheckMenuItemSetActiveCaller;
274
275 GtkCheckMenuItem* create_check_menu_item_with_mnemonic( GtkMenu* menu, const char* mnemonic, const Toggle& toggle ){
276         GtkCheckMenuItem* item = create_check_menu_item_with_mnemonic( menu, mnemonic, toggle.m_command.m_callback );
277         menu_item_add_accelerator( GTK_MENU_ITEM( item ), toggle.m_command.m_accelerator );
278         toggle.m_exportCallback( CheckMenuItemSetActiveCaller( *item ) );
279         return item;
280 }