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++)
new_signals[class->nsignals + i] = signals[i];
g_free (class->signals);
class->signals = new_signals;
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:
*

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.
*/
guint gtk_object_get_type (void);
@ -171,6 +183,15 @@ void gtk_object_class_add_signals (GtkObjectClass *klass,
gint *signals,
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,
...);

View File

@ -161,15 +161,60 @@ gtk_signal_new (const gchar *name,
...)
{
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;
GtkSignalInfo info;
gint *type;
gint i;
va_list args;
guint i;
g_return_val_if_fail (name != 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)
gtk_signal_init ();
@ -186,35 +231,56 @@ gtk_signal_new (const gchar *name,
}
signal = g_new (GtkSignal, 1);
signal->info.name = g_strdup(name);
signal->info.name = g_strdup (name);
signal->info.object_type = object_type;
signal->info.signal_type = next_signal++;
signal->function_offset = function_offset;
signal->run_type = run_type;
signal->marshaller = marshaller;
signal->return_val = return_val;
signal->params = NULL;
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)
{
signal->params = g_new (GtkType, nparams);
params = signal->params;
va_start (args, nparams);
for (i = 0; i < nparams; i++)
params[i] = va_arg (args, GtkType);
va_end (args);
signal->params[i] = params[i];
}
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;
}
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
gtk_signal_lookup (const gchar *name,
gint object_type)
@ -871,7 +937,7 @@ gtk_signal_real_emit (GtkObject *object,
gtk_emission_add (&current_emissions, object, signal_type);
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);
if (*signal_func_offset)
@ -898,7 +964,7 @@ gtk_signal_real_emit (GtkObject *object,
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);
if (*signal_func_offset)
@ -965,31 +1031,44 @@ gtk_signal_connect_by_type (GtkObject *object,
gint after,
gint no_marshal)
{
GtkObjectClass *class;
GtkHandler *handler;
gint *object_signals;
gint nsignals;
gint found_it;
gint i;
g_return_val_if_fail (object != 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
* sure the one we are adding is valid. If it isn't then
* issue a warning and return.
* sure the one we are adding is valid. We need to perform
* 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;
for (i = 0; i < nsignals; i++)
if (object_signals[i] == signal_type)
{
found_it = TRUE;
break;
}
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++)
if (object_signals[i] == signal_type)
{
found_it = TRUE;
break;
}
parent = gtk_type_parent (class->type);
if (parent)
class = gtk_type_class (parent);
else
class = NULL;
}
if (!found_it)
{
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))
#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,
gpointer data,
gint nparams,
@ -51,6 +44,18 @@ typedef void (*GtkSignalMarshal) (GtkObject *object,
GtkType return_type);
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,
GtkSignalRunType run_type,
@ -60,6 +65,14 @@ gint gtk_signal_new (const gchar *name,
GtkType return_val,
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 object_type);
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,
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
}

View File

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