new user signal, and possibility to query signal information.

-timj
This commit is contained in:
Tim Janik 1998-01-29 20:44:14 +00:00
parent 22388cfc07
commit db6a8d4a8a
5 changed files with 216 additions and 40 deletions

View File

@ -256,10 +256,65 @@ gtk_object_class_add_signals (GtkObjectClass *class,
for (i = 0; i < nsignals; i++) for (i = 0; i < nsignals; i++)
new_signals[class->nsignals + i] = signals[i]; new_signals[class->nsignals + i] = signals[i];
g_free (class->signals);
class->signals = new_signals; class->signals = new_signals;
class->nsignals += nsignals; class->nsignals += nsignals;
} }
/*****************************************
* gtk_object_class_add_user_signal:
*
* arguments:
*
* results:
*****************************************/
gint
gtk_object_class_add_user_signal (GtkObjectClass *class,
const gchar *name,
GtkSignalMarshaller marshaller,
GtkType return_val,
gint nparams,
...)
{
GtkType *params;
guint i;
va_list args;
gint signal_id;
g_return_val_if_fail (class != NULL, 0);
if (nparams > 0)
{
params = g_new (GtkType, nparams);
va_start (args, nparams);
for (i = 0; i < nparams; i++)
params[i] = va_arg (args, GtkType);
va_end (args);
}
else
params = NULL;
signal_id = gtk_signal_newv (name,
0,
class->type,
0,
marshaller,
return_val,
nparams,
params);
g_free (params);
if (signal_id)
gtk_object_class_add_signals (class, &signal_id, 1);
return signal_id;
}
/***************************************** /*****************************************
* gtk_object_ref: * gtk_object_ref:
* *

View File

@ -161,6 +161,18 @@ struct _GtkObjectClass
}; };
/* For the purpose of user signals we need the signal function
* and signal marshaller signatures already in this place.
*/
#define GTK_SIGNAL_FUNC(f) ((GtkSignalFunc) f)
typedef void (*GtkSignalFunc) (void);
typedef void (*GtkSignalMarshaller) (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
/* Get the type identifier for GtkObject's. /* Get the type identifier for GtkObject's.
*/ */
guint gtk_object_get_type (void); guint gtk_object_get_type (void);
@ -171,6 +183,15 @@ void gtk_object_class_add_signals (GtkObjectClass *klass,
gint *signals, gint *signals,
gint nsignals); gint nsignals);
/* Append a user defined signal without default handler to a class.
*/
gint gtk_object_class_add_user_signal (GtkObjectClass *klass,
const gchar *name,
GtkSignalMarshaller marshaller,
GtkType return_val,
gint nparams,
...);
GtkObject* gtk_object_new (guint type, GtkObject* gtk_object_new (guint type,
...); ...);

View File

@ -161,15 +161,60 @@ gtk_signal_new (const gchar *name,
...) ...)
{ {
GtkType *params; GtkType *params;
guint i;
va_list args;
gint return_id;
g_return_val_if_fail (nparams < 16, 0);
if (nparams > 0)
{
params = g_new (GtkType, nparams);
va_start (args, nparams);
for (i = 0; i < nparams; i++)
params[i] = va_arg (args, GtkType);
va_end (args);
}
else
params = NULL;
return_id = gtk_signal_newv (name,
run_type,
object_type,
function_offset,
marshaller,
return_val,
nparams,
params);
g_free (params);
return return_id;
}
gint
gtk_signal_newv (const gchar *name,
GtkSignalRunType run_type,
gint object_type,
gint function_offset,
GtkSignalMarshaller marshaller,
GtkType return_val,
gint nparams,
GtkType *params)
{
GtkSignal *signal; GtkSignal *signal;
GtkSignalInfo info; GtkSignalInfo info;
gint *type; gint *type;
gint i; guint i;
va_list args;
g_return_val_if_fail (name != NULL, 0); g_return_val_if_fail (name != NULL, 0);
g_return_val_if_fail (marshaller != NULL, 0); g_return_val_if_fail (marshaller != NULL, 0);
g_return_val_if_fail (nparams < 10, 0); g_return_val_if_fail (nparams < 16, 0);
if (nparams)
g_return_val_if_fail (params != NULL, 0);
if (initialize) if (initialize)
gtk_signal_init (); gtk_signal_init ();
@ -193,28 +238,49 @@ gtk_signal_new (const gchar *name,
signal->run_type = run_type; signal->run_type = run_type;
signal->marshaller = marshaller; signal->marshaller = marshaller;
signal->return_val = return_val; signal->return_val = return_val;
signal->params = NULL;
signal->nparams = nparams; signal->nparams = nparams;
g_hash_table_insert (signal_hash_table, &signal->info.signal_type, signal);
g_hash_table_insert (signal_info_hash_table, &signal->info, &signal->info.signal_type);
if (nparams > 0) if (nparams > 0)
{ {
signal->params = g_new (GtkType, nparams); signal->params = g_new (GtkType, nparams);
params = signal->params;
va_start (args, nparams);
for (i = 0; i < nparams; i++) for (i = 0; i < nparams; i++)
params[i] = va_arg (args, GtkType); signal->params[i] = params[i];
va_end (args);
} }
else
signal->params = NULL;
g_hash_table_insert (signal_hash_table, &signal->info.signal_type, signal);
g_hash_table_insert (signal_info_hash_table, &signal->info, &signal->info.signal_type);
return signal->info.signal_type; return signal->info.signal_type;
} }
GtkSignalQuery*
gtk_signal_query (gint signal_num)
{
GtkSignalQuery *query;
GtkSignal *signal;
signal = g_hash_table_lookup (signal_hash_table, &signal_num);
if (signal)
{
query = g_new (GtkSignalQuery, 1);
query->object_type = signal->info.object_type;
query->signal_name = signal->info.name;
query->is_user_signal = signal->function_offset == 0;
query->run_type = signal->run_type;
query->return_val = signal->return_val;
query->nparams = signal->nparams;
query->params = signal->params;
}
else
query = NULL;
return query;
}
gint gint
gtk_signal_lookup (const gchar *name, gtk_signal_lookup (const gchar *name,
gint object_type) gint object_type)
@ -871,7 +937,7 @@ gtk_signal_real_emit (GtkObject *object,
gtk_emission_add (&current_emissions, object, signal_type); gtk_emission_add (&current_emissions, object, signal_type);
restart: restart:
if (GTK_RUN_TYPE (signal->run_type) != GTK_RUN_LAST) if (GTK_RUN_TYPE (signal->run_type) != GTK_RUN_LAST && signal->function_offset != 0)
{ {
signal_func_offset = (guchar**) ((guchar*) object->klass + signal->function_offset); signal_func_offset = (guchar**) ((guchar*) object->klass + signal->function_offset);
if (*signal_func_offset) if (*signal_func_offset)
@ -898,7 +964,7 @@ gtk_signal_real_emit (GtkObject *object,
goto restart; goto restart;
} }
if (GTK_RUN_TYPE (signal->run_type) != GTK_RUN_FIRST) if (GTK_RUN_TYPE (signal->run_type) != GTK_RUN_FIRST && signal->function_offset != 0)
{ {
signal_func_offset = (guchar**) ((guchar*) object->klass + signal->function_offset); signal_func_offset = (guchar**) ((guchar*) object->klass + signal->function_offset);
if (*signal_func_offset) if (*signal_func_offset)
@ -965,23 +1031,29 @@ gtk_signal_connect_by_type (GtkObject *object,
gint after, gint after,
gint no_marshal) gint no_marshal)
{ {
GtkObjectClass *class;
GtkHandler *handler; GtkHandler *handler;
gint *object_signals;
gint nsignals;
gint found_it; gint found_it;
gint i;
g_return_val_if_fail (object != NULL, 0); g_return_val_if_fail (object != NULL, 0);
g_return_val_if_fail (object->klass != NULL, 0); g_return_val_if_fail (object->klass != NULL, 0);
g_return_val_if_fail (object->klass->signals != NULL, 0);
/* Search through the signals for this object and make /* Search through the signals for this object and make
* sure the one we are adding is valid. If it isn't then * sure the one we are adding is valid. We need to perform
* issue a warning and return. * the lookup on the objects parents as well. If it isn't
* valid then issue a warning and return.
*/ */
object_signals = object->klass->signals;
nsignals = object->klass->nsignals;
found_it = FALSE; found_it = FALSE;
class = object->klass;
while (class)
{
GtkType parent;
gint *object_signals;
gint nsignals;
guint i;
object_signals = class->signals;
nsignals = class->nsignals;
for (i = 0; i < nsignals; i++) for (i = 0; i < nsignals; i++)
if (object_signals[i] == signal_type) if (object_signals[i] == signal_type)
@ -990,6 +1062,13 @@ gtk_signal_connect_by_type (GtkObject *object,
break; break;
} }
parent = gtk_type_parent (class->type);
if (parent)
class = gtk_type_class (parent);
else
class = NULL;
}
if (!found_it) if (!found_it)
{ {
g_warning ("could not find signal (%d) in object's list of signals", signal_type); g_warning ("could not find signal (%d) in object's list of signals", signal_type);

View File

@ -35,14 +35,7 @@ extern "C" {
#define GTK_SIGNAL_OFFSET(t, f) ((int) ((char*) &((t*) 0)->f)) #define GTK_SIGNAL_OFFSET(t, f) ((int) ((char*) &((t*) 0)->f))
#endif /* offsetof */ #endif /* offsetof */
#define GTK_SIGNAL_FUNC(f) ((GtkSignalFunc) f)
typedef void (*GtkSignalFunc) (void);
typedef void (*GtkSignalMarshaller) (GtkObject *object,
GtkSignalFunc func,
gpointer func_data,
GtkArg *args);
typedef void (*GtkSignalMarshal) (GtkObject *object, typedef void (*GtkSignalMarshal) (GtkObject *object,
gpointer data, gpointer data,
gint nparams, gint nparams,
@ -51,6 +44,18 @@ typedef void (*GtkSignalMarshal) (GtkObject *object,
GtkType return_type); GtkType return_type);
typedef void (*GtkSignalDestroy) (gpointer data); typedef void (*GtkSignalDestroy) (gpointer data);
typedef struct _GtkSignalQuery GtkSignalQuery;
struct _GtkSignalQuery
{
gint object_type;
const gchar *signal_name;
gboolean is_user_signal;
GtkSignalRunType run_type;
GtkType return_val;
guint nparams;
const GtkType *params;
};
gint gtk_signal_new (const gchar *name, gint gtk_signal_new (const gchar *name,
GtkSignalRunType run_type, GtkSignalRunType run_type,
@ -60,6 +65,14 @@ gint gtk_signal_new (const gchar *name,
GtkType return_val, GtkType return_val,
gint nparams, gint nparams,
...); ...);
gint gtk_signal_newv (const gchar *name,
GtkSignalRunType run_type,
gint object_type,
gint function_offset,
GtkSignalMarshaller marshaller,
GtkType return_val,
gint nparams,
GtkType *params);
gint gtk_signal_lookup (const gchar *name, gint gtk_signal_lookup (const gchar *name,
gint object_type); gint object_type);
gchar* gtk_signal_name (gint signal_num); gchar* gtk_signal_name (gint signal_num);
@ -115,6 +128,12 @@ void gtk_signal_default_marshaller (GtkObject *object,
void gtk_signal_set_funcs (GtkSignalMarshal marshal_func, void gtk_signal_set_funcs (GtkSignalMarshal marshal_func,
GtkSignalDestroy destroy_func); GtkSignalDestroy destroy_func);
/* Report internal information about a signal. The caller has the response
* to invoke a supsequent g_free (returned_data); but must leave the
* contents of GtkSignalQuery untouched.
*/
GtkSignalQuery* gtk_signal_query (gint signal_num);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -356,6 +356,8 @@ gtk_type_class_init (GtkTypeNode *node)
object_class = node->klass; object_class = node->klass;
object_class->type = node->type; object_class->type = node->type;
object_class->signals = NULL;
object_class->nsignals = 0;
object_class->n_args = 0; object_class->n_args = 0;
if (node->type_info.class_init_func) if (node->type_info.class_init_func)