GObject patch
- From: Eric Lemings <eric b lemings lmco com>
- To: gtk-devel-list gnome org
- Subject: GObject patch
- Date: Fri, 27 Oct 2000 15:43:32 -0600
Hello all,
Attached is a patch to gobject.h and gobject.c that allows an object to
be notified using GSignal of param changes to another object.
For example:
/* The GGizmoClass has a "name" parameter.
*/
subject = g_object_new (G_TYPE_GIZMO, NULL);
/* Notify observer if "name" param changes for subject.
*/
observer = g_object_new (G_TYPE_OBJECT, NULL);
g_object_notify_param_changed (subject, "name", observer);
/* Emits a param changed signal.
*/
g_object_set (subject, "name", "Gimp", NULL);
I tested it out and it works like a charm. Enjoy!
Eric.
--- gobject.h.orig Fri Oct 27 12:06:56 2000
+++ gobject.h Fri Oct 27 14:50:52 2000
@@ -92,7 +92,8 @@
void (*queue_param_changed) (GObject *object,
GParamSpec *pspec);
void (*dispatch_param_changed) (GObject *object,
- GParamSpec *pspec);
+ GParamSpec *pspec,
+ GObject *subject);
void (*shutdown) (GObject *object);
void (*finalize) (GObject *object);
};
@@ -136,6 +137,9 @@
GValue *value);
void g_object_queue_param_changed (GObject *object,
const gchar *param_name);
+guint g_object_notify_param_changed (GObject *object,
+ const gchar *param_name,
+ GObject *subject);
GObject* g_object_ref (GObject *object);
void g_object_unref (GObject *object);
gpointer g_object_get_qdata (GObject *object,
--- gobject.c.orig Thu Oct 26 18:26:38 2000
+++ gobject.c Fri Oct 27 15:16:41 2000
@@ -21,6 +21,8 @@
#include "gobject.h"
#include "gvaluecollector.h"
+#include "gsignal.h"
+#include "gvaluetypes.h"
#define DEBUG_OBJECTS
@@ -38,10 +40,17 @@
static void g_object_do_queue_param_changed (GObject *object,
GParamSpec *pspec);
static void g_object_do_dispatch_param_changed (GObject *object,
- GParamSpec *pspec);
+ GParamSpec *pspec,
+ GObject *subject);
static void g_object_last_unref (GObject *object);
static void g_object_do_shutdown (GObject *object);
static void g_object_do_finalize (GObject *object);
+static void g_object_VOID__POINTER (GClosure* closure,
+ guint invocation_hint,
+ GValue* return_value,
+ guint n_param_values,
+ const GValue* param_values,
+ gpointer marshal_data);
static void g_value_object_init (GValue *value);
static void g_value_object_free_value (GValue *value);
static void g_value_object_copy_value (const GValue *src_value,
@@ -57,11 +66,19 @@
GTypeCValue *collect_value);
+/* --- constants --- */
+enum {
+ PARAM_CHANGED,
+ LAST_SIGNAL
+};
+
+
/* --- variables --- */
static GQuark quark_param_id = 0;
static GQuark quark_param_changed_queue = 0;
static GQuark quark_closure_array = 0;
static GHashTable *param_spec_hash_table = NULL;
+static guint object_signals [LAST_SIGNAL];
/* --- functions --- */
@@ -179,6 +196,9 @@
static void
g_object_do_class_init (GObjectClass *class)
{
+ GClosure *closure = NULL;
+ GType param_types[] = { G_TYPE_POINTER };
+
quark_param_id = g_quark_from_static_string ("glib-object-param-id");
quark_param_changed_queue = g_quark_from_static_string ("glib-object-param-changed-queue");
quark_closure_array = g_quark_from_static_string ("GObject-closure-array");
@@ -186,6 +206,15 @@
class->queue_param_changed = g_object_do_queue_param_changed;
class->dispatch_param_changed = g_object_do_dispatch_param_changed;
+
+ closure = g_signal_type_closure_new (G_TYPE_FROM_CLASS (class),
+ G_STRUCT_OFFSET (GObjectClass,
+ dispatch_param_changed));
+ object_signals[PARAM_CHANGED] = g_signal_newv ("glib-object-param-changed-signal",
+ G_TYPE_OBJECT, (GSignalType)0,
+ closure, NULL, g_object_VOID__POINTER,
+ G_TYPE_NONE, 1, param_types);
+
class->shutdown = g_object_do_shutdown;
class->finalize = g_object_do_finalize;
}
@@ -338,13 +367,50 @@
return object;
}
+void
+g_object_VOID__POINTER (GClosure *closure,
+ guint invocation_hint,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer marshal_data)
+{
+ typedef void (*GSignalFunc_VOID__POINTER) (gpointer data1,
+ gpointer arg_1,
+ gpointer data2);
+ register GSignalFunc_VOID__POINTER callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values >= 2);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_get_as_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_get_as_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+
+ callback = (GSignalFunc_VOID__POINTER) (marshal_data ? marshal_data : cc->callback);
+ callback (data1,
+ g_value_get_as_pointer (param_values + 1),
+ data2);
+}
+
static void
g_object_do_dispatch_param_changed (GObject *object,
- GParamSpec *pspec)
+ GParamSpec *pspec,
+ GObject *subject)
{
-/* g_message ("NOTIFICATION: parameter `%s' changed on object `%s'",
+ g_message ("NOTIFICATION: object `%s' notified that parameter `%s' "
+ "changed on object `%s'",
+ G_OBJECT_TYPE_NAME (object),
pspec->name,
- G_OBJECT_TYPE_NAME (object));*/
+ G_OBJECT_TYPE_NAME (subject));
}
static gboolean
@@ -368,7 +434,7 @@
GParamSpec *pspec = slist->data;
slist->data = NULL;
- class->dispatch_param_changed (object, pspec);
+ class->dispatch_param_changed (object, pspec, object);
}
g_datalist_id_set_data (&object->qdata, quark_param_changed_queue, NULL);
@@ -425,6 +491,20 @@
class->get_param (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
}
+static void
+object_param_changed (GObject *object,
+ GParamSpec *pspec)
+{
+ GValue values[2] = { { 0, } };
+
+ g_value_init (values, G_TYPE_POINTER);
+ g_value_set_pointer (values, (gpointer) object);
+ g_value_init (values+1, G_TYPE_POINTER);
+ g_value_set_pointer (values+1, (gpointer) pspec);
+
+ g_signal_emitv (values, object_signals [PARAM_CHANGED], NULL);
+}
+
static inline void
object_set_param (GObject *object,
GValue *value,
@@ -440,6 +520,8 @@
class->set_param (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
class->queue_param_changed (object, pspec);
+
+ object_param_changed (object, pspec);
}
void
@@ -724,6 +806,40 @@
param_name);
else
G_OBJECT_GET_CLASS (object)->queue_param_changed (object, pspec);
+}
+
+guint
+g_object_notify_param_changed (GObject *object,
+ const gchar *param_name,
+ GObject *subject)
+{
+ GParamSpec *pspec;
+ guint handler_id = 0;
+
+ g_return_val_if_fail (G_IS_OBJECT (object), 0);
+ g_return_val_if_fail (param_name != NULL, 0);
+ g_return_val_if_fail (G_IS_OBJECT (subject), 0);
+
+ pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
+ param_name,
+ G_OBJECT_TYPE (object),
+ TRUE, NULL);
+ if (!pspec)
+ g_warning ("%s: object class `%s' has no parameter named `%s'",
+ G_STRLOC,
+ G_OBJECT_TYPE_NAME (object),
+ param_name);
+ else
+ {
+ GObjectClass *class = G_OBJECT_GET_CLASS (object);
+ GClosure *closure = g_cclosure_new_swap (class->dispatch_param_changed,
+ subject, NULL);
+ handler_id = g_signal_connect_closure (object,
+ object_signals [PARAM_CHANGED],
+ closure, FALSE);
+ }
+
+ return (handler_id);
}
GObject*
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]