2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
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.
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.
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
26 #include <uilib/uilib.h>
27 #include <debugging/debugging.h>
29 #include "generic/callback.h"
31 #include "accelerator.h"
33 #include "container.h"
36 void menu_add_item( ui::Menu menu, ui::MenuItem item ){
40 ui::MenuItem menu_separator( ui::Menu menu ){
41 auto menu_item = ui::MenuItem(GTK_MENU_ITEM( gtk_menu_item_new() ));
42 container_add_widget( menu, menu_item );
43 gtk_widget_set_sensitive( GTK_WIDGET( menu_item ), FALSE );
48 ui::TearoffMenuItem menu_tearoff( ui::Menu menu ){
49 auto menu_item = ui::TearoffMenuItem(GTK_TEAROFF_MENU_ITEM( gtk_tearoff_menu_item_new() ));
50 container_add_widget( menu, menu_item );
51 // gtk_widget_set_sensitive(GTK_WIDGET(menu_item), FALSE); -- controls whether menu is detachable
56 ui::MenuItem new_sub_menu_item_with_mnemonic( const char* mnemonic ){
57 auto item = ui::MenuItem( mnemonic, true );
60 auto sub_menu = ui::Menu();
61 gtk_menu_item_set_submenu( item, sub_menu );
66 ui::Menu create_sub_menu_with_mnemonic( ui::MenuShell parent, const char* mnemonic ){
67 auto item = new_sub_menu_item_with_mnemonic( mnemonic );
68 container_add_widget( parent, item );
69 return ui::Menu(GTK_MENU( gtk_menu_item_get_submenu( item ) ));
72 ui::Menu create_sub_menu_with_mnemonic( ui::MenuBar bar, const char* mnemonic ){
73 return create_sub_menu_with_mnemonic( ui::MenuShell(GTK_MENU_SHELL( bar )), mnemonic );
76 ui::Menu create_sub_menu_with_mnemonic( ui::Menu parent, const char* mnemonic ){
77 return create_sub_menu_with_mnemonic( ui::MenuShell(GTK_MENU_SHELL( parent )), mnemonic );
80 void activate_closure_callback( ui::Widget widget, gpointer data ){
81 ( *reinterpret_cast<Callback*>( data ) )( );
84 guint menu_item_connect_callback( ui::MenuItem item, const Callback& callback ){
86 return g_signal_connect_swapped( G_OBJECT( item ), "activate", G_CALLBACK( callback.getThunk() ), callback.getEnvironment() );
88 return g_signal_connect_closure( G_OBJECT( item ), "activate", create_cclosure( G_CALLBACK( activate_closure_callback ), callback ), FALSE );
92 guint check_menu_item_connect_callback( ui::CheckMenuItem item, const Callback& callback ){
94 guint handler = g_signal_connect_swapped( G_OBJECT( item ), "toggled", G_CALLBACK( callback.getThunk() ), callback.getEnvironment() );
96 guint handler = g_signal_connect_closure( G_OBJECT( item ), "toggled", create_cclosure( G_CALLBACK( activate_closure_callback ), callback ), TRUE );
98 g_object_set_data( G_OBJECT( item ), "handler", gint_to_pointer( handler ) );
102 ui::MenuItem new_menu_item_with_mnemonic( const char *mnemonic, const Callback& callback ){
103 auto item = ui::MenuItem( mnemonic, true );
105 menu_item_connect_callback( item, callback );
109 ui::MenuItem create_menu_item_with_mnemonic( ui::Menu menu, const char *mnemonic, const Callback& callback ){
110 auto item = new_menu_item_with_mnemonic( mnemonic, callback );
111 container_add_widget( menu, item );
115 ui::CheckMenuItem new_check_menu_item_with_mnemonic( const char* mnemonic, const Callback& callback ){
116 auto item = ui::CheckMenuItem(GTK_CHECK_MENU_ITEM( gtk_check_menu_item_new_with_mnemonic( mnemonic ) ));
118 check_menu_item_connect_callback( item, callback );
122 ui::CheckMenuItem create_check_menu_item_with_mnemonic( ui::Menu menu, const char* mnemonic, const Callback& callback ){
123 auto item = new_check_menu_item_with_mnemonic( mnemonic, callback );
124 container_add_widget( menu, item );
128 ui::RadioMenuItem new_radio_menu_item_with_mnemonic( GSList** group, const char* mnemonic, const Callback& callback ){
129 auto item = ui::RadioMenuItem(GTK_RADIO_MENU_ITEM( gtk_radio_menu_item_new_with_mnemonic( *group, mnemonic ) ));
131 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( item ), TRUE );
133 *group = gtk_radio_menu_item_get_group( item );
135 check_menu_item_connect_callback( item, callback );
139 ui::RadioMenuItem create_radio_menu_item_with_mnemonic( ui::Menu menu, GSList** group, const char* mnemonic, const Callback& callback ){
140 auto item = new_radio_menu_item_with_mnemonic( group, mnemonic, callback );
141 container_add_widget( menu, item );
145 void check_menu_item_set_active_no_signal( ui::CheckMenuItem item, gboolean active ){
146 guint handler_id = gpointer_to_int( g_object_get_data( G_OBJECT( item ), "handler" ) );
147 g_signal_handler_block( G_OBJECT( item ), handler_id );
148 gtk_check_menu_item_set_active( item, active );
149 g_signal_handler_unblock( G_OBJECT( item ), handler_id );
154 void radio_menu_item_set_active_no_signal( ui::RadioMenuItem item, gboolean active ){
156 for ( GSList* l = gtk_radio_menu_item_get_group( item ); l != 0; l = g_slist_next( l ) )
158 g_signal_handler_block( G_OBJECT( l->data ), gpointer_to_int( g_object_get_data( G_OBJECT( l->data ), "handler" ) ) );
161 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( item ), active );
163 for ( GSList* l = gtk_radio_menu_item_get_group( item ); l != 0; l = g_slist_next( l ) )
165 g_signal_handler_unblock( G_OBJECT( l->data ), gpointer_to_int( g_object_get_data( G_OBJECT( l->data ), "handler" ) ) );
171 void menu_item_set_accelerator( ui::MenuItem item, GClosure* closure ){
172 GtkAccelLabel* accel_label = GTK_ACCEL_LABEL( gtk_bin_get_child( GTK_BIN( item ) ) );
173 gtk_accel_label_set_accel_closure( accel_label, closure );
176 void accelerator_name( const Accelerator& accelerator, GString* gstring ){
177 gboolean had_mod = FALSE;
178 if ( accelerator.modifiers & GDK_SHIFT_MASK ) {
179 g_string_append( gstring, "Shift" );
182 if ( accelerator.modifiers & GDK_CONTROL_MASK ) {
184 g_string_append( gstring, "+" );
186 g_string_append( gstring, "Ctrl" );
189 if ( accelerator.modifiers & GDK_MOD1_MASK ) {
191 g_string_append( gstring, "+" );
193 g_string_append( gstring, "Alt" );
198 g_string_append( gstring, "+" );
200 if ( accelerator.key < 0x80 || ( accelerator.key > 0x80 && accelerator.key <= 0xff ) ) {
201 switch ( accelerator.key )
204 g_string_append( gstring, "Space" );
207 g_string_append( gstring, "Backslash" );
210 g_string_append_c( gstring, gchar( toupper( accelerator.key ) ) );
218 tmp = gtk_accelerator_name( accelerator.key, (GdkModifierType)0 );
219 if ( tmp[0] != 0 && tmp[1] == 0 ) {
220 tmp[0] = gchar( toupper( tmp[0] ) );
222 g_string_append( gstring, tmp );
227 void menu_item_add_accelerator( ui::MenuItem item, Accelerator accelerator ){
228 if ( accelerator.key != 0 && gtk_accelerator_valid( accelerator.key, accelerator.modifiers )) {
229 GClosure* closure = global_accel_group_find( accelerator );
230 ASSERT_NOTNULL(closure);
231 menu_item_set_accelerator( item, closure );
235 ui::MenuItem create_menu_item_with_mnemonic( ui::Menu menu, const char* mnemonic, const Command& command ){
236 auto item = create_menu_item_with_mnemonic( menu, mnemonic, command.m_callback );
237 menu_item_add_accelerator( item, command.m_accelerator );
241 void check_menu_item_set_active_callback( GtkCheckMenuItem &item, bool enabled ){
242 check_menu_item_set_active_no_signal( ui::CheckMenuItem(&item), enabled );
244 typedef ReferenceCaller1<GtkCheckMenuItem, bool, check_menu_item_set_active_callback> CheckMenuItemSetActiveCaller;
246 ui::CheckMenuItem create_check_menu_item_with_mnemonic( ui::Menu menu, const char* mnemonic, const Toggle& toggle ){
247 auto item = create_check_menu_item_with_mnemonic( menu, mnemonic, toggle.m_command.m_callback );
248 menu_item_add_accelerator( item, toggle.m_command.m_accelerator );
249 GtkCheckMenuItem *item_ = item;
250 toggle.m_exportCallback( CheckMenuItemSetActiveCaller( *item_ ) );