📄 gtkitemfactory.c
字号:
/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * GtkItemFactory: Flexible item factory with automatic rc handling * Copyright (C) 1998 Tim Janik * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */#include "gtkitemfactory.h"#include "gtk/gtksignal.h"#include "gtk/gtkoptionmenu.h"#include "gtk/gtkmenubar.h"#include "gtk/gtkmenu.h"#include "gtk/gtkmenuitem.h"#include "gtk/gtkradiomenuitem.h"#include "gtk/gtkcheckmenuitem.h"#include "gtk/gtktearoffmenuitem.h"#include "gtk/gtkaccellabel.h"#include "gdk/gdkkeysyms.h"#include <string.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <stdio.h>/* --- defines --- */#define ITEM_FACTORY_STRING ((gchar*) item_factory_string)#define ITEM_BLOCK_SIZE (128)/* --- structures --- */typedef struct _GtkIFCBData GtkIFCBData;typedef struct _GtkIFDumpData GtkIFDumpData;struct _GtkIFCBData{ GtkItemFactoryCallback func; guint callback_type; gpointer func_data; guint callback_action;};struct _GtkIFDumpData{ GtkPrintFunc print_func; gpointer func_data; guint modified_only : 1; GtkPatternSpec *pspec;};/* --- prototypes --- */static void gtk_item_factory_class_init (GtkItemFactoryClass *klass);static void gtk_item_factory_init (GtkItemFactory *ifactory);static void gtk_item_factory_destroy (GtkObject *object);static void gtk_item_factory_finalize (GtkObject *object);/* --- static variables --- */static GtkItemFactoryClass *gtk_item_factory_class = NULL;static GtkObjectClass *parent_class = NULL;static const gchar *item_factory_string = "Gtk-<ItemFactory>";static GMemChunk *ifactory_item_chunks = NULL;static GMemChunk *ifactory_cb_data_chunks = NULL;static GQuark quark_popup_data = 0;static GQuark quark_if_menu_pos = 0;static GQuark quark_item_factory = 0;static GQuark quark_item_path = 0;static GQuark quark_action = 0;static GQuark quark_accel_group = 0;static GQuark quark_type_item = 0;static GQuark quark_type_title = 0;static GQuark quark_type_radio_item = 0;static GQuark quark_type_check_item = 0;static GQuark quark_type_toggle_item = 0;static GQuark quark_type_tearoff_item = 0;static GQuark quark_type_separator_item = 0;static GQuark quark_type_branch = 0;static GQuark quark_type_last_branch = 0;static GScannerConfig ifactory_scanner_config ={ ( " \t\n" ) /* cset_skip_characters */, ( G_CSET_a_2_z "_" G_CSET_A_2_Z ) /* cset_identifier_first */, ( G_CSET_a_2_z "-+_0123456789" G_CSET_A_2_Z G_CSET_LATINS G_CSET_LATINC ) /* cset_identifier_nth */, ( ";\n" ) /* cpair_comment_single */, FALSE /* case_sensitive */, TRUE /* skip_comment_multi */, TRUE /* skip_comment_single */, FALSE /* scan_comment_multi */, TRUE /* scan_identifier */, FALSE /* scan_identifier_1char */, FALSE /* scan_identifier_NULL */, TRUE /* scan_symbols */, TRUE /* scan_binary */, TRUE /* scan_octal */, TRUE /* scan_float */, TRUE /* scan_hex */, FALSE /* scan_hex_dollar */, TRUE /* scan_string_sq */, TRUE /* scan_string_dq */, TRUE /* numbers_2_int */, FALSE /* int_2_float */, FALSE /* identifier_2_string */, TRUE /* char_2_token */, FALSE /* symbol_2_token */,};/* --- functions --- */GtkTypegtk_item_factory_get_type (void){ static GtkType item_factory_type = 0; if (!item_factory_type) { static const GtkTypeInfo item_factory_info = { "GtkItemFactory", sizeof (GtkItemFactory), sizeof (GtkItemFactoryClass), (GtkClassInitFunc) gtk_item_factory_class_init, (GtkObjectInitFunc) gtk_item_factory_init, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; item_factory_type = gtk_type_unique (GTK_TYPE_OBJECT, &item_factory_info); } return item_factory_type;}static voidgtk_item_factory_class_init (GtkItemFactoryClass *class){ GtkObjectClass *object_class; gtk_item_factory_class = class; parent_class = gtk_type_class (GTK_TYPE_OBJECT); object_class = (GtkObjectClass*) class; object_class->destroy = gtk_item_factory_destroy; object_class->finalize = gtk_item_factory_finalize; class->cpair_comment_single = g_strdup (";\n"); class->item_ht = g_hash_table_new (g_str_hash, g_str_equal); class->dummy = NULL; ifactory_item_chunks = g_mem_chunk_new ("GtkItemFactoryItem", sizeof (GtkItemFactoryItem), sizeof (GtkItemFactoryItem) * ITEM_BLOCK_SIZE, G_ALLOC_ONLY); ifactory_cb_data_chunks = g_mem_chunk_new ("GtkIFCBData", sizeof (GtkIFCBData), sizeof (GtkIFCBData) * ITEM_BLOCK_SIZE, G_ALLOC_AND_FREE); quark_popup_data = g_quark_from_static_string ("GtkItemFactory-popup-data"); quark_if_menu_pos = g_quark_from_static_string ("GtkItemFactory-menu-position"); quark_item_factory = g_quark_from_static_string ("GtkItemFactory"); quark_item_path = g_quark_from_static_string ("GtkItemFactory-path"); quark_action = g_quark_from_static_string ("GtkItemFactory-action"); quark_accel_group = g_quark_from_static_string ("GtkAccelGroup"); quark_type_item = g_quark_from_static_string ("<Item>"); quark_type_title = g_quark_from_static_string ("<Title>"); quark_type_radio_item = g_quark_from_static_string ("<RadioItem>"); quark_type_check_item = g_quark_from_static_string ("<CheckItem>"); quark_type_toggle_item = g_quark_from_static_string ("<ToggleItem>"); quark_type_tearoff_item = g_quark_from_static_string ("<Tearoff>"); quark_type_separator_item = g_quark_from_static_string ("<Separator>"); quark_type_branch = g_quark_from_static_string ("<Branch>"); quark_type_last_branch = g_quark_from_static_string ("<LastBranch>");}static voidgtk_item_factory_init (GtkItemFactory *ifactory){ GtkObject *object; object = GTK_OBJECT (ifactory); ifactory->path = NULL; ifactory->accel_group = NULL; ifactory->widget = NULL; ifactory->items = NULL; ifactory->translate_func = NULL; ifactory->translate_data = NULL; ifactory->translate_notify = NULL;}GtkItemFactory*gtk_item_factory_new (GtkType container_type, const gchar *path, GtkAccelGroup *accel_group){ GtkItemFactory *ifactory; g_return_val_if_fail (path != NULL, NULL); ifactory = gtk_type_new (GTK_TYPE_ITEM_FACTORY); gtk_item_factory_construct (ifactory, container_type, path, accel_group); return ifactory;}static voidgtk_item_factory_callback_marshal (GtkWidget *widget, gpointer func_data){ GtkIFCBData *data; data = func_data; if (data->callback_type == 1) { GtkItemFactoryCallback1 func1 = data->func; func1 (data->func_data, data->callback_action, widget); } else if (data->callback_type == 2) { GtkItemFactoryCallback2 func2 = data->func; func2 (widget, data->func_data, data->callback_action); }}static voidgtk_item_factory_propagate_accelerator (GtkItemFactoryItem *item, GtkWidget *exclude){ GSList *widget_list; GSList *slist; if (item->in_propagation) return; item->in_propagation = TRUE; widget_list = NULL; for (slist = item->widgets; slist; slist = slist->next) { GtkWidget *widget; widget = slist->data; if (widget != exclude) { gtk_widget_ref (widget); widget_list = g_slist_prepend (widget_list, widget); } } for (slist = widget_list; slist; slist = slist->next) { GtkWidget *widget; GtkAccelGroup *accel_group; guint signal_id; widget = slist->data; accel_group = gtk_object_get_data_by_id (GTK_OBJECT (widget), quark_accel_group); signal_id = gtk_signal_lookup ("activate", GTK_OBJECT_TYPE (widget)); if (signal_id && accel_group) { if (item->accelerator_key) gtk_widget_add_accelerator (widget, "activate", accel_group, item->accelerator_key, item->accelerator_mods, GTK_ACCEL_VISIBLE); else { GSList *work; work = gtk_accel_group_entries_from_object (GTK_OBJECT (widget)); while (work) { GtkAccelEntry *ac_entry; ac_entry = work->data; work = work->next; if (ac_entry->accel_flags & GTK_ACCEL_VISIBLE && ac_entry->accel_group == accel_group && ac_entry->signal_id == signal_id) gtk_widget_remove_accelerator (GTK_WIDGET (widget), ac_entry->accel_group, ac_entry->accelerator_key, ac_entry->accelerator_mods); } } } gtk_widget_unref (widget); } g_slist_free (widget_list); item->in_propagation = FALSE;}static gintgtk_item_factory_item_add_accelerator (GtkWidget *widget, guint accel_signal_id, GtkAccelGroup *accel_group, guint accel_key, guint accel_mods, GtkAccelFlags accel_flags, GtkItemFactoryItem *item){ if (!item->in_propagation && g_slist_find (item->widgets, widget) && accel_signal_id == gtk_signal_lookup ("activate", GTK_OBJECT_TYPE (widget))) { item->accelerator_key = accel_key; item->accelerator_mods = accel_mods; item->modified = TRUE; gtk_item_factory_propagate_accelerator (item, widget); } return TRUE;}static voidgtk_item_factory_item_remove_accelerator (GtkWidget *widget, GtkAccelGroup *accel_group, guint accel_key, guint accel_mods, GtkItemFactoryItem *item){ if (!item->in_propagation && g_slist_find (item->widgets, widget) && item->accelerator_key == accel_key && item->accelerator_mods == accel_mods) { item->accelerator_key = 0; item->accelerator_mods = 0; item->modified = TRUE; gtk_item_factory_propagate_accelerator (item, widget); }}static voidgtk_item_factory_item_remove_widget (GtkWidget *widget, GtkItemFactoryItem *item){ item->widgets = g_slist_remove (item->widgets, widget); gtk_object_remove_data_by_id (GTK_OBJECT (widget), quark_item_factory); gtk_object_remove_data_by_id (GTK_OBJECT (widget), quark_item_path);}voidgtk_item_factory_add_foreign (GtkWidget *accel_widget, const gchar *full_path, GtkAccelGroup *accel_group, guint keyval, GdkModifierType modifiers){ GtkItemFactoryClass *class; GtkItemFactoryItem *item; g_return_if_fail (GTK_IS_WIDGET (accel_widget)); g_return_if_fail (full_path != NULL); class = gtk_type_class (GTK_TYPE_ITEM_FACTORY); keyval = keyval != GDK_VoidSymbol ? keyval : 0; item = g_hash_table_lookup (class->item_ht, full_path); if (!item) { item = g_chunk_new (GtkItemFactoryItem, ifactory_item_chunks); item->path = g_strdup (full_path); item->accelerator_key = keyval; item->accelerator_mods = modifiers; item->modified = FALSE; item->in_propagation = FALSE; item->dummy = NULL; item->widgets = NULL; g_hash_table_insert (class->item_ht, item->path, item); } item->widgets = g_slist_prepend (item->widgets, accel_widget); gtk_signal_connect (GTK_OBJECT (accel_widget), "destroy", GTK_SIGNAL_FUNC (gtk_item_factory_item_remove_widget), item); /* set the item path for the widget */ gtk_object_set_data_by_id (GTK_OBJECT (accel_widget), quark_item_path, item->path); gtk_widget_set_name (accel_widget, item->path); if (accel_group) { gtk_accel_group_ref (accel_group); gtk_object_set_data_by_id_full (GTK_OBJECT (accel_widget), quark_accel_group, accel_group, (GtkDestroyNotify) gtk_accel_group_unref); } else gtk_object_set_data_by_id (GTK_OBJECT (accel_widget), quark_accel_group, NULL); /* install defined accelerators */ if (gtk_signal_lookup ("activate", GTK_OBJECT_TYPE (accel_widget))) { if (item->accelerator_key && accel_group) gtk_widget_add_accelerator (accel_widget, "activate", accel_group, item->accelerator_key, item->accelerator_mods, GTK_ACCEL_VISIBLE); else gtk_widget_remove_accelerators (accel_widget, "activate", TRUE); } /* keep track of accelerator changes */ gtk_signal_connect_after (GTK_OBJECT (accel_widget), "add-accelerator", GTK_SIGNAL_FUNC (gtk_item_factory_item_add_accelerator), item); gtk_signal_connect_after (GTK_OBJECT (accel_widget), "remove-accelerator", GTK_SIGNAL_FUNC (gtk_item_factory_item_remove_accelerator), item);}static voidifactory_cb_data_free (gpointer mem){ g_mem_chunk_free (ifactory_cb_data_chunks, mem);}static voidgtk_item_factory_add_item (GtkItemFactory *ifactory, const gchar *path, const gchar *accelerator, GtkItemFactoryCallback callback, guint callback_action, gpointer callback_data, guint callback_type, gchar *item_type, GtkWidget *widget){ GtkItemFactoryClass *class; GtkItemFactoryItem *item; gchar *fpath; guint keyval, mods; g_return_if_fail (widget != NULL); g_return_if_fail (item_type != NULL); class = GTK_ITEM_FACTORY_CLASS (GTK_OBJECT (ifactory)->klass); /* set accelerator group on menu widgets */ if (GTK_IS_MENU (widget)) gtk_menu_set_accel_group ((GtkMenu*) widget, ifactory->accel_group); /* connect callback if neccessary */ if (callback) { GtkIFCBData *data; data = g_chunk_new (GtkIFCBData, ifactory_cb_data_chunks); data->func = callback; data->callback_type = callback_type; data->func_data = callback_data; data->callback_action = callback_action; gtk_object_weakref (GTK_OBJECT (widget), ifactory_cb_data_free, data); gtk_signal_connect (GTK_OBJECT (widget), "activate", GTK_SIGNAL_FUNC (gtk_item_factory_callback_marshal), data); } /* link the widget into its item-entry * and keep back pointer on both the item factory and the widget */ gtk_object_set_data_by_id (GTK_OBJECT (widget), quark_action, GUINT_TO_POINTER (callback_action)); gtk_object_set_data_by_id (GTK_OBJECT (widget), quark_item_factory, ifactory); if (accelerator) gtk_accelerator_parse (accelerator, &keyval, &mods); else { keyval = 0; mods = 0; } fpath = g_strconcat (ifactory->path, path, NULL); gtk_item_factory_add_foreign (widget, fpath, ifactory->accel_group, keyval, mods); item = g_hash_table_lookup (class->item_ht, fpath); g_free (fpath); g_return_if_fail (item != NULL); if (!g_slist_find (ifactory->items, item)) ifactory->items = g_slist_prepend (ifactory->items, item);}voidgtk_item_factory_construct (GtkItemFactory *ifactory, GtkType container_type, const gchar *path, GtkAccelGroup *accel_group){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -