/* Copyright (C) 2001-2006, William Joseph. All Rights Reserved. This file is part of GtkRadiant. GtkRadiant is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GtkRadiant is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "menu.h" #include #include #include #include #include #include #include "generic/callback.h" #include "accelerator.h" #include "closure.h" #include "container.h" #include "pointer.h" void menu_add_item( GtkMenu* menu, GtkMenuItem* item ){ gtk_container_add( GTK_CONTAINER( menu ), GTK_WIDGET( item ) ); } GtkMenuItem* menu_separator( GtkMenu* menu ){ GtkMenuItem* menu_item = GTK_MENU_ITEM( gtk_menu_item_new() ); container_add_widget( GTK_CONTAINER( menu ), GTK_WIDGET( menu_item ) ); gtk_widget_set_sensitive( GTK_WIDGET( menu_item ), FALSE ); gtk_widget_show( GTK_WIDGET( menu_item ) ); return menu_item; } GtkTearoffMenuItem* menu_tearoff( GtkMenu* menu ){ GtkTearoffMenuItem* menu_item = GTK_TEAROFF_MENU_ITEM( gtk_tearoff_menu_item_new() ); container_add_widget( GTK_CONTAINER( menu ), GTK_WIDGET( menu_item ) ); // gtk_widget_set_sensitive(GTK_WIDGET(menu_item), FALSE); -- controls whether menu is detachable gtk_widget_show( GTK_WIDGET( menu_item ) ); return menu_item; } GtkMenuItem* new_sub_menu_item_with_mnemonic( const char* mnemonic ){ GtkMenuItem* item = GTK_MENU_ITEM( gtk_menu_item_new_with_mnemonic( mnemonic ) ); gtk_widget_show( GTK_WIDGET( item ) ); GtkWidget* sub_menu = gtk_menu_new(); gtk_menu_item_set_submenu( item, sub_menu ); return item; } GtkMenu* create_sub_menu_with_mnemonic( GtkMenuShell* parent, const char* mnemonic ){ GtkMenuItem* item = new_sub_menu_item_with_mnemonic( mnemonic ); container_add_widget( GTK_CONTAINER( parent ), GTK_WIDGET( item ) ); return GTK_MENU( gtk_menu_item_get_submenu( item ) ); } GtkMenu* create_sub_menu_with_mnemonic( GtkMenuBar* bar, const char* mnemonic ){ return create_sub_menu_with_mnemonic( GTK_MENU_SHELL( bar ), mnemonic ); } GtkMenu* create_sub_menu_with_mnemonic( GtkMenu* parent, const char* mnemonic ){ return create_sub_menu_with_mnemonic( GTK_MENU_SHELL( parent ), mnemonic ); } void activate_closure_callback( GtkWidget* widget, gpointer data ){ ( *reinterpret_cast( data ) )( ); } guint menu_item_connect_callback( GtkMenuItem* item, const Callback& callback ){ #if 1 return g_signal_connect_swapped( G_OBJECT( item ), "activate", G_CALLBACK( callback.getThunk() ), callback.getEnvironment() ); #else return g_signal_connect_closure( G_OBJECT( item ), "activate", create_cclosure( G_CALLBACK( activate_closure_callback ), callback ), FALSE ); #endif } guint check_menu_item_connect_callback( GtkCheckMenuItem* item, const Callback& callback ){ #if 1 guint handler = g_signal_connect_swapped( G_OBJECT( item ), "toggled", G_CALLBACK( callback.getThunk() ), callback.getEnvironment() ); #else guint handler = g_signal_connect_closure( G_OBJECT( item ), "toggled", create_cclosure( G_CALLBACK( activate_closure_callback ), callback ), TRUE ); #endif g_object_set_data( G_OBJECT( item ), "handler", gint_to_pointer( handler ) ); return handler; } GtkMenuItem* new_menu_item_with_mnemonic( const char *mnemonic, const Callback& callback ){ GtkMenuItem* item = GTK_MENU_ITEM( gtk_menu_item_new_with_mnemonic( mnemonic ) ); gtk_widget_show( GTK_WIDGET( item ) ); menu_item_connect_callback( item, callback ); return item; } GtkMenuItem* create_menu_item_with_mnemonic( GtkMenu* menu, const char *mnemonic, const Callback& callback ){ GtkMenuItem* item = new_menu_item_with_mnemonic( mnemonic, callback ); container_add_widget( GTK_CONTAINER( menu ), GTK_WIDGET( item ) ); return item; } GtkCheckMenuItem* new_check_menu_item_with_mnemonic( const char* mnemonic, const Callback& callback ){ GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM( gtk_check_menu_item_new_with_mnemonic( mnemonic ) ); gtk_widget_show( GTK_WIDGET( item ) ); check_menu_item_connect_callback( item, callback ); return item; } GtkCheckMenuItem* create_check_menu_item_with_mnemonic( GtkMenu* menu, const char* mnemonic, const Callback& callback ){ GtkCheckMenuItem* item = new_check_menu_item_with_mnemonic( mnemonic, callback ); container_add_widget( GTK_CONTAINER( menu ), GTK_WIDGET( item ) ); return item; } GtkRadioMenuItem* new_radio_menu_item_with_mnemonic( GSList** group, const char* mnemonic, const Callback& callback ){ GtkRadioMenuItem* item = GTK_RADIO_MENU_ITEM( gtk_radio_menu_item_new_with_mnemonic( *group, mnemonic ) ); if ( *group == 0 ) { gtk_check_menu_item_set_state( GTK_CHECK_MENU_ITEM( item ), TRUE ); } *group = gtk_radio_menu_item_group( item ); gtk_widget_show( GTK_WIDGET( item ) ); check_menu_item_connect_callback( GTK_CHECK_MENU_ITEM( item ), callback ); return item; } GtkRadioMenuItem* create_radio_menu_item_with_mnemonic( GtkMenu* menu, GSList** group, const char* mnemonic, const Callback& callback ){ GtkRadioMenuItem* item = new_radio_menu_item_with_mnemonic( group, mnemonic, callback ); container_add_widget( GTK_CONTAINER( menu ), GTK_WIDGET( item ) ); return item; } void check_menu_item_set_active_no_signal( GtkCheckMenuItem* item, gboolean active ){ guint handler_id = gpointer_to_int( g_object_get_data( G_OBJECT( item ), "handler" ) ); g_signal_handler_block( G_OBJECT( item ), handler_id ); gtk_check_menu_item_set_active( item, active ); g_signal_handler_unblock( G_OBJECT( item ), handler_id ); } void radio_menu_item_set_active_no_signal( GtkRadioMenuItem* item, gboolean active ){ { for ( GSList* l = gtk_radio_menu_item_get_group( item ); l != 0; l = g_slist_next( l ) ) { g_signal_handler_block( G_OBJECT( l->data ), gpointer_to_int( g_object_get_data( G_OBJECT( l->data ), "handler" ) ) ); } } gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( item ), active ); { for ( GSList* l = gtk_radio_menu_item_get_group( item ); l != 0; l = g_slist_next( l ) ) { g_signal_handler_unblock( G_OBJECT( l->data ), gpointer_to_int( g_object_get_data( G_OBJECT( l->data ), "handler" ) ) ); } } } void menu_item_set_accelerator( GtkMenuItem* item, GClosure* closure ){ GtkAccelLabel* accel_label = GTK_ACCEL_LABEL( gtk_bin_get_child( GTK_BIN( item ) ) ); gtk_accel_label_set_accel_closure( accel_label, closure ); } void accelerator_name( const Accelerator& accelerator, GString* gstring ){ gboolean had_mod = FALSE; if ( accelerator.modifiers & GDK_SHIFT_MASK ) { g_string_append( gstring, "Shift" ); had_mod = TRUE; } if ( accelerator.modifiers & GDK_CONTROL_MASK ) { if ( had_mod ) { g_string_append( gstring, "+" ); } g_string_append( gstring, "Ctrl" ); had_mod = TRUE; } if ( accelerator.modifiers & GDK_MOD1_MASK ) { if ( had_mod ) { g_string_append( gstring, "+" ); } g_string_append( gstring, "Alt" ); had_mod = TRUE; } if ( had_mod ) { g_string_append( gstring, "+" ); } if ( accelerator.key < 0x80 || ( accelerator.key > 0x80 && accelerator.key <= 0xff ) ) { switch ( accelerator.key ) { case ' ': g_string_append( gstring, "Space" ); break; case '\\': g_string_append( gstring, "Backslash" ); break; default: g_string_append_c( gstring, gchar( toupper( accelerator.key ) ) ); break; } } else { gchar *tmp; tmp = gtk_accelerator_name( accelerator.key, (GdkModifierType)0 ); if ( tmp[0] != 0 && tmp[1] == 0 ) { tmp[0] = gchar( toupper( tmp[0] ) ); } g_string_append( gstring, tmp ); g_free( tmp ); } } void menu_item_set_accelerator( GtkMenuItem* item, Accelerator accelerator ){ GtkAccelLabel* accel_label = GTK_ACCEL_LABEL( gtk_bin_get_child( GTK_BIN( item ) ) ); g_free( accel_label->accel_string ); accel_label->accel_string = 0; GString* gstring = g_string_new( accel_label->accel_string ); g_string_append( gstring, " " ); accelerator_name( accelerator, gstring ); g_free( accel_label->accel_string ); accel_label->accel_string = gstring->str; g_string_free( gstring, FALSE ); if ( !accel_label->accel_string ) { accel_label->accel_string = g_strdup( "" ); } gtk_widget_queue_resize( GTK_WIDGET( accel_label ) ); } void menu_item_add_accelerator( GtkMenuItem* item, Accelerator accelerator ){ if ( accelerator.key != 0 ) { GClosure* closure = global_accel_group_find( accelerator ); if ( closure != 0 ) { menu_item_set_accelerator( item, closure ); } else { menu_item_set_accelerator( item, accelerator ); } } } GtkMenuItem* create_menu_item_with_mnemonic( GtkMenu* menu, const char* mnemonic, const Command& command ){ GtkMenuItem* item = create_menu_item_with_mnemonic( menu, mnemonic, command.m_callback ); menu_item_add_accelerator( item, command.m_accelerator ); return item; } void check_menu_item_set_active_callback( GtkCheckMenuItem& item, bool enabled ){ check_menu_item_set_active_no_signal( &item, enabled ); } typedef ReferenceCaller1 CheckMenuItemSetActiveCaller; GtkCheckMenuItem* create_check_menu_item_with_mnemonic( GtkMenu* menu, const char* mnemonic, const Toggle& toggle ){ GtkCheckMenuItem* item = create_check_menu_item_with_mnemonic( menu, mnemonic, toggle.m_command.m_callback ); menu_item_add_accelerator( GTK_MENU_ITEM( item ), toggle.m_command.m_accelerator ); toggle.m_exportCallback( CheckMenuItemSetActiveCaller( *item ) ); return item; }