[gnome-builder] egg-binding-set: add grouped GBinding helper
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] egg-binding-set: add grouped GBinding helper
- Date: Sat, 2 May 2015 09:00:47 +0000 (UTC)
commit 14a94f260fc1a4087706fd1f880c01063b4b3931
Author: Christian Hergert <christian hergert me>
Date: Sat May 2 01:45:56 2015 -0700
egg-binding-set: add grouped GBinding helper
EggBindingSet let's you create a group of bindings that you would like
to apply in the future on an, yet unknown, object. Simply call
egg_binding_set_set_source() with the source object for the binding
at some point in the future and the bindings will be applied.
You can change the source at any time to apply the bindings to a new
source instance.
contrib/egg/Makefile.am | 2 +
contrib/egg/egg-binding-set.c | 374 +++++++++++++++++++++++++++++++++++++++++
contrib/egg/egg-binding-set.h | 42 +++++
3 files changed, 418 insertions(+), 0 deletions(-)
---
diff --git a/contrib/egg/Makefile.am b/contrib/egg/Makefile.am
index fa8a0ee..dc6b3bf 100644
--- a/contrib/egg/Makefile.am
+++ b/contrib/egg/Makefile.am
@@ -1,6 +1,8 @@
noinst_LTLIBRARIES = libegg.la
libegg_la_SOURCES = \
+ egg-binding-set.c \
+ egg-binding-set.h \
egg-signal-group.c \
egg-signal-group.h \
$(NULL)
diff --git a/contrib/egg/egg-binding-set.c b/contrib/egg/egg-binding-set.c
new file mode 100644
index 0000000..04a99dd
--- /dev/null
+++ b/contrib/egg/egg-binding-set.c
@@ -0,0 +1,374 @@
+/* egg-binding-set.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This file 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n.h>
+
+#include "egg-binding-set.h"
+
+/**
+ * SECTION:egg-binding-set
+ * @title: EggBindingSet
+ * @short_description: Manage multiple #GBinding as a group.
+ *
+ * This should not be confused with #GtkBindingSet.
+ *
+ * #EggBindingSet allows you to manage a set of #GBinding that you would like attached to the
+ * same source object. This is convenience so that you can manage them as a set rather than
+ * reconnecting them individually.
+ */
+
+struct _EggBindingSet
+{
+ GObject parent_instance;
+
+ GObject *source;
+ GPtrArray *lazy_bindings;
+};
+
+typedef struct
+{
+ const gchar *source_property;
+ const gchar *target_property;
+ GObject *target;
+ GBinding *binding;
+ GBindingFlags binding_flags;
+} LazyBinding;
+
+G_DEFINE_TYPE (EggBindingSet, egg_binding_set, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_SOURCE,
+ LAST_PROP
+};
+
+static GParamSpec *gParamSpecs [LAST_PROP];
+
+EggBindingSet *
+egg_binding_set_new (void)
+{
+ return g_object_new (EGG_TYPE_BINDING_SET, NULL);
+}
+
+static void
+lazy_binding_free (gpointer data)
+{
+ LazyBinding *lazy_binding = data;
+
+ if (lazy_binding != NULL)
+ {
+ if (lazy_binding->binding != NULL)
+ {
+ g_binding_unbind (lazy_binding->binding);
+ lazy_binding->binding = NULL;
+ }
+
+ g_assert (lazy_binding->target == NULL);
+
+ lazy_binding->source_property = NULL;
+ lazy_binding->target_property = NULL;
+ }
+}
+
+static void
+egg_binding_set_connect (EggBindingSet *self,
+ LazyBinding *lazy_binding)
+{
+ g_assert (EGG_IS_BINDING_SET (self));
+ g_assert (self->source != NULL);
+ g_assert (lazy_binding != NULL);
+ g_assert (lazy_binding->binding == NULL);
+ g_assert (lazy_binding->target != NULL);
+ g_assert (lazy_binding->target_property != NULL);
+ g_assert (lazy_binding->source_property != NULL);
+
+ lazy_binding->binding = g_object_bind_property (self->source,
+ lazy_binding->source_property,
+ lazy_binding->target,
+ lazy_binding->target_property,
+ lazy_binding->binding_flags);
+}
+
+static void
+egg_binding_set_disconnect (EggBindingSet *self,
+ LazyBinding *lazy_binding)
+{
+ GBinding *binding;
+
+ g_assert (EGG_IS_BINDING_SET (self));
+ g_assert (lazy_binding != NULL);
+
+ binding = lazy_binding->binding;
+
+ if (binding != NULL)
+ {
+ lazy_binding->binding = NULL;
+ g_binding_unbind (binding);
+ }
+}
+
+static void
+egg_binding_set__source_weak_notify (gpointer data,
+ GObject *where_object_was)
+{
+ EggBindingSet *self = data;
+ gsize i;
+
+ g_assert (EGG_IS_BINDING_SET (self));
+
+ self->source = NULL;
+
+ for (i = 0; i < self->lazy_bindings->len; i++)
+ {
+ LazyBinding *lazy_binding;
+
+ lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
+ lazy_binding->binding = NULL;
+ }
+}
+
+static void
+egg_binding_set__target_weak_notify (gpointer data,
+ GObject *where_object_was)
+{
+ EggBindingSet *self = data;
+ gsize i;
+
+ g_assert (EGG_IS_BINDING_SET (self));
+
+ for (i = 0; i < self->lazy_bindings->len; i++)
+ {
+ LazyBinding *lazy_binding;
+
+ lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
+
+ if (lazy_binding->target == where_object_was)
+ {
+ lazy_binding->target = NULL;
+ lazy_binding->binding = NULL;
+
+ g_ptr_array_remove_index_fast (self->lazy_bindings, i);
+ break;
+ }
+ }
+}
+
+static void
+egg_binding_set_dispose (GObject *object)
+{
+ EggBindingSet *self = (EggBindingSet *)object;
+ gsize i;
+
+ g_assert (EGG_IS_BINDING_SET (self));
+
+ if (self->source != NULL)
+ {
+ g_object_weak_unref (self->source,
+ egg_binding_set__source_weak_notify,
+ self);
+ self->source = NULL;
+ }
+
+ for (i = 0; i < self->lazy_bindings->len; i++)
+ {
+ LazyBinding *lazy_binding;
+
+ lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
+
+ egg_binding_set_disconnect (self, lazy_binding);
+
+ if (lazy_binding->target != NULL)
+ {
+ g_object_weak_unref (lazy_binding->target,
+ egg_binding_set__target_weak_notify,
+ self);
+ lazy_binding->target = NULL;
+ }
+ }
+
+ if (self->lazy_bindings->len != 0)
+ g_ptr_array_remove_range (self->lazy_bindings, 0, self->lazy_bindings->len);
+
+ G_OBJECT_CLASS (egg_binding_set_parent_class)->dispose (object);
+}
+
+static void
+egg_binding_set_finalize (GObject *object)
+{
+ EggBindingSet *self = (EggBindingSet *)object;
+
+ g_assert (self->lazy_bindings != NULL);
+ g_assert_cmpint (self->lazy_bindings->len, ==, 0);
+
+ g_clear_pointer (&self->lazy_bindings, g_ptr_array_unref);
+ g_clear_object (&self->source);
+
+ G_OBJECT_CLASS (egg_binding_set_parent_class)->finalize (object);
+}
+
+static void
+egg_binding_set_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EggBindingSet *self = EGG_BINDING_SET (object);
+
+ switch (prop_id)
+ {
+ case PROP_SOURCE:
+ g_value_set_object (value, egg_binding_set_get_source (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+egg_binding_set_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EggBindingSet *self = EGG_BINDING_SET (object);
+
+ switch (prop_id)
+ {
+ case PROP_SOURCE:
+ egg_binding_set_set_source (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+egg_binding_set_class_init (EggBindingSetClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = egg_binding_set_dispose;
+ object_class->finalize = egg_binding_set_finalize;
+ object_class->get_property = egg_binding_set_get_property;
+ object_class->set_property = egg_binding_set_set_property;
+
+ gParamSpecs [PROP_SOURCE] =
+ g_param_spec_object ("source",
+ _("Source"),
+ _("The source GObject."),
+ G_TYPE_OBJECT,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class, PROP_SOURCE, gParamSpecs [PROP_SOURCE]);
+}
+
+static void
+egg_binding_set_init (EggBindingSet *self)
+{
+ self->lazy_bindings = g_ptr_array_new_with_free_func (lazy_binding_free);
+}
+
+gpointer
+egg_binding_set_get_source (EggBindingSet *self)
+{
+ g_return_val_if_fail (EGG_IS_BINDING_SET (self), NULL);
+
+ return self->source;
+}
+
+void
+egg_binding_set_set_source (EggBindingSet *self,
+ gpointer source)
+{
+ g_return_if_fail (EGG_IS_BINDING_SET (self));
+ g_return_if_fail (!source || G_IS_OBJECT (source));
+ g_return_if_fail (source != (gpointer)self);
+
+ if (source != (gpointer)self->source)
+ {
+ if (self->source != NULL)
+ {
+ gsize i;
+
+ g_object_weak_unref (self->source,
+ egg_binding_set__source_weak_notify,
+ self);
+ self->source = NULL;
+
+ for (i = 0; i < self->lazy_bindings->len; i++)
+ {
+ LazyBinding *lazy_binding;
+
+ lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
+ egg_binding_set_disconnect (self, lazy_binding);
+ }
+ }
+
+ if (source != NULL)
+ {
+ gsize i;
+
+ self->source = source;
+ g_object_weak_ref (self->source,
+ egg_binding_set__source_weak_notify,
+ self);
+
+ for (i = 0; i < self->lazy_bindings->len; i++)
+ {
+ LazyBinding *lazy_binding;
+
+ lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
+ egg_binding_set_connect (self, lazy_binding);
+ }
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (self), gParamSpecs [PROP_SOURCE]);
+ }
+}
+
+void
+egg_binding_set_bind (EggBindingSet *self,
+ const gchar *source_property,
+ gpointer target,
+ const gchar *target_property,
+ GBindingFlags flags)
+{
+ LazyBinding *lazy_binding;
+
+ g_return_if_fail (EGG_IS_BINDING_SET (self));
+ g_return_if_fail (source_property != NULL);
+ g_return_if_fail (G_IS_OBJECT (target));
+ g_return_if_fail (target_property != NULL);
+ g_return_if_fail (target != (gpointer)self);
+
+ lazy_binding = g_slice_new0 (LazyBinding);
+ lazy_binding->source_property = g_intern_string (source_property);
+ lazy_binding->target_property = g_intern_string (target_property);
+ lazy_binding->target = target;
+ lazy_binding->binding_flags = flags;
+
+ g_object_weak_ref (target,
+ egg_binding_set__target_weak_notify,
+ self);
+
+ g_ptr_array_add (self->lazy_bindings, lazy_binding);
+
+ if (self->source != NULL)
+ egg_binding_set_connect (self, lazy_binding);
+}
diff --git a/contrib/egg/egg-binding-set.h b/contrib/egg/egg-binding-set.h
new file mode 100644
index 0000000..30ef756
--- /dev/null
+++ b/contrib/egg/egg-binding-set.h
@@ -0,0 +1,42 @@
+/* egg-binding-set.h
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This file 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EGG_BINDING_SET_H
+#define EGG_BINDING_SET_H
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_BINDING_SET (egg_binding_set_get_type())
+
+G_DECLARE_FINAL_TYPE (EggBindingSet, egg_binding_set, EGG, BINDING_SET, GObject)
+
+EggBindingSet *egg_binding_set_new (void);
+gpointer egg_binding_set_get_source (EggBindingSet *self);
+void egg_binding_set_set_source (EggBindingSet *self,
+ gpointer source);
+void egg_binding_set_bind (EggBindingSet *self,
+ const gchar *source_property,
+ gpointer target,
+ const gchar *target_property,
+ GBindingFlags flags);
+
+G_END_DECLS
+
+#endif /* EGG_BINDING_SET_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]