/* 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 "generic/callback.h" #include "accelerator.h" #include "closure.h" #include "container.h" #include "pointer.h" void menu_add_item(ui::Menu menu, ui::MenuItem item) { menu.add(item); } ui::MenuItem menu_separator(ui::Menu menu) { auto menu_item = ui::MenuItem::from(gtk_menu_item_new()); menu.add(menu_item); gtk_widget_set_sensitive(menu_item, FALSE); menu_item.show(); return menu_item; } ui::TearoffMenuItem menu_tearoff(ui::Menu menu) { auto menu_item = ui::TearoffMenuItem::from(gtk_tearoff_menu_item_new()); menu.add(menu_item); // gtk_widget_set_sensitive(menu_item, FALSE); -- controls whether menu is detachable menu_item.show(); return menu_item; } ui::MenuItem new_sub_menu_item_with_mnemonic(const char *mnemonic) { auto item = ui::MenuItem(mnemonic, true); item.show(); auto sub_menu = ui::Menu(ui::New); gtk_menu_item_set_submenu(item, sub_menu); return item; } ui::Menu create_sub_menu_with_mnemonic(ui::MenuShell parent, const char *mnemonic) { auto item = new_sub_menu_item_with_mnemonic(mnemonic); parent.add(item); return ui::Menu::from(gtk_menu_item_get_submenu(item)); } ui::Menu create_sub_menu_with_mnemonic(ui::MenuBar bar, const char *mnemonic) { return create_sub_menu_with_mnemonic(ui::MenuShell::from(bar._handle), mnemonic); } ui::Menu create_sub_menu_with_mnemonic(ui::Menu parent, const char *mnemonic) { return create_sub_menu_with_mnemonic(ui::MenuShell::from(parent._handle), mnemonic); } void activate_closure_callback(ui::Widget widget, gpointer data) { (*reinterpret_cast *>( data ))(); } guint menu_item_connect_callback(ui::MenuItem 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(ui::CheckMenuItem 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; } ui::MenuItem new_menu_item_with_mnemonic(const char *mnemonic, const Callback &callback) { auto item = ui::MenuItem(mnemonic, true); item.show(); menu_item_connect_callback(item, callback); return item; } ui::MenuItem create_menu_item_with_mnemonic(ui::Menu menu, const char *mnemonic, const Callback &callback) { auto item = new_menu_item_with_mnemonic(mnemonic, callback); menu.add(item); return item; } ui::CheckMenuItem new_check_menu_item_with_mnemonic(const char *mnemonic, const Callback &callback) { auto item = ui::CheckMenuItem::from(gtk_check_menu_item_new_with_mnemonic(mnemonic)); item.show(); check_menu_item_connect_callback(item, callback); return item; } ui::CheckMenuItem create_check_menu_item_with_mnemonic(ui::Menu menu, const char *mnemonic, const Callback &callback) { auto item = new_check_menu_item_with_mnemonic(mnemonic, callback); menu.add(item); return item; } ui::RadioMenuItem new_radio_menu_item_with_mnemonic(GSList **group, const char *mnemonic, const Callback &callback) { auto item = ui::RadioMenuItem::from(gtk_radio_menu_item_new_with_mnemonic(*group, mnemonic)); if (*group == 0) { gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); } *group = gtk_radio_menu_item_get_group(item); item.show(); check_menu_item_connect_callback(item, callback); return item; } ui::RadioMenuItem create_radio_menu_item_with_mnemonic(ui::Menu menu, GSList **group, const char *mnemonic, const Callback &callback) { auto item = new_radio_menu_item_with_mnemonic(group, mnemonic, callback); menu.add(item); return item; } void check_menu_item_set_active_no_signal(ui::CheckMenuItem 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(ui::RadioMenuItem 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(ui::MenuItem 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_add_accelerator(ui::MenuItem item, Accelerator accelerator) { if (accelerator.key != 0 && gtk_accelerator_valid(accelerator.key, accelerator.modifiers)) { GClosure *closure = global_accel_group_find(accelerator); ASSERT_NOTNULL(closure); menu_item_set_accelerator(item, closure); } } ui::MenuItem create_menu_item_with_mnemonic(ui::Menu menu, const char *mnemonic, const Command &command) { auto 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(void *it, bool enabled) { auto item = ui::CheckMenuItem::from(it); check_menu_item_set_active_no_signal(item, enabled); } ui::CheckMenuItem create_check_menu_item_with_mnemonic(ui::Menu menu, const char *mnemonic, const Toggle &toggle) { auto item = create_check_menu_item_with_mnemonic(menu, mnemonic, toggle.m_command.m_callback); menu_item_add_accelerator(item, toggle.m_command.m_accelerator); toggle.m_exportCallback(PointerCaller(item._handle)); return item; }