constraint: Add BindConstraint
authorEmmanuele Bassi <ebassi@linux.intel.com>
Wed, 19 May 2010 11:25:28 +0000 (12:25 +0100)
committerEmmanuele Bassi <ebassi@linux.intel.com>
Wed, 19 May 2010 11:28:35 +0000 (12:28 +0100)
The BindConstraint object is a constraint that binds the current
position of an actor on a given axis to the actor that has the
constraint applied.

clutter/Makefile.am
clutter/clutter-bind-constraint.c [new file with mode: 0644]
clutter/clutter-bind-constraint.h [new file with mode: 0644]
clutter/clutter.h

index 9571cd2..e753d91 100644 (file)
@@ -80,6 +80,7 @@ source_h =                                    \
        $(srcdir)/clutter-behaviour-path.h      \
        $(srcdir)/clutter-behaviour-rotate.h    \
        $(srcdir)/clutter-behaviour-scale.h     \
+       $(srcdir)/clutter-bind-constraint.h     \
        $(srcdir)/clutter-binding-pool.h        \
        $(srcdir)/clutter-bin-layout.h          \
        $(srcdir)/clutter-box.h                 \
@@ -158,6 +159,7 @@ source_c = \
        $(srcdir)/clutter-behaviour-rotate.c    \
        $(srcdir)/clutter-behaviour-scale.c     \
        $(srcdir)/clutter-bezier.c              \
+       $(srcdir)/clutter-bind-constraint.c     \
        $(srcdir)/clutter-binding-pool.c        \
        $(srcdir)/clutter-bin-layout.c          \
        $(srcdir)/clutter-box.c                 \
diff --git a/clutter/clutter-bind-constraint.c b/clutter/clutter-bind-constraint.c
new file mode 100644 (file)
index 0000000..199b3f5
--- /dev/null
@@ -0,0 +1,267 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "clutter-bind-constraint.h"
+
+#include "clutter-constraint.h"
+#include "clutter-debug.h"
+#include "clutter-enum-types.h"
+#include "clutter-private.h"
+
+#define CLUTTER_BIND_CONSTRAINT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BIND_CONSTRAINT, ClutterBindConstraintClass))
+#define CLUTTER_IS_BIND_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BIND_CONSTRAINT))
+#define CLUTTER_BIND_CONSTRAINT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BIND_CONSTRAINT, ClutterBindConstraintClass))
+
+typedef struct _ClutterBindConstraintClass      ClutterBindConstraintClass;
+
+struct _ClutterBindConstraint
+{
+  ClutterConstraint parent_instance;
+
+  ClutterActor *source;
+  ClutterBindAxis bind_axis;
+  gfloat offset;
+};
+
+struct _ClutterBindConstraintClass
+{
+  ClutterConstraintClass parent_class;
+};
+
+enum
+{
+  PROP_0,
+
+  PROP_SOURCE,
+  PROP_BIND_AXIS,
+  PROP_OFFSET
+};
+
+G_DEFINE_TYPE (ClutterBindConstraint,
+               clutter_bind_constraint,
+               CLUTTER_TYPE_CONSTRAINT);
+
+static void
+update_actor_position (ClutterBindConstraint *bind)
+{
+  ClutterVertex source_position;
+  ClutterActor *actor;
+
+  if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (bind)))
+    return;
+
+  actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (bind));
+  if (actor == NULL)
+    return;
+
+  source_position.x = clutter_actor_get_x (bind->source);
+  source_position.y = clutter_actor_get_y (bind->source);
+  source_position.z = clutter_actor_get_depth (bind->source);
+
+  switch (bind->bind_axis)
+    {
+    case CLUTTER_BIND_X_AXIS:
+      clutter_actor_set_x (actor, source_position.x + bind->offset);
+      break;
+
+    case CLUTTER_BIND_Y_AXIS:
+      clutter_actor_set_y (actor, source_position.y + bind->offset);
+      break;
+
+    case CLUTTER_BIND_Z_AXIS:
+      clutter_actor_set_depth (actor, source_position.z + bind->offset);
+      break;
+    }
+}
+
+static void
+source_position_changed (GObject               *gobject,
+                         GParamSpec            *pspec,
+                         ClutterBindConstraint *bind)
+{
+  if (strcmp (pspec->name, "x") == 0 ||
+      strcmp (pspec->name, "y") == 0 ||
+      strcmp (pspec->name, "depth") == 0)
+    {
+      update_actor_position (bind);
+    }
+}
+
+static void
+source_destroyed (ClutterActor *actor,
+                  ClutterBindConstraint *bind)
+{
+  bind->source = NULL;
+}
+
+static void
+_clutter_bind_constraint_set_source (ClutterBindConstraint *bind,
+                                     ClutterActor          *source)
+{
+  ClutterActor *old_source = bind->source;
+
+  if (old_source != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (old_source,
+                                            G_CALLBACK (source_destroyed),
+                                            bind);
+      g_signal_handlers_disconnect_by_func (old_source,
+                                            G_CALLBACK (source_position_changed),
+                                            bind);
+    }
+
+  bind->source = source;
+  g_signal_connect (bind->source, "notify",
+                    G_CALLBACK (source_position_changed),
+                    bind);
+  g_signal_connect (bind->source, "destroy",
+                    G_CALLBACK (source_destroyed),
+                    bind);
+
+  update_actor_position (bind);
+
+  g_object_notify (G_OBJECT (bind), "source");
+}
+
+static void
+_clutter_bind_constraint_set_bind_axis (ClutterBindConstraint *bind,
+                                        ClutterBindAxis        axis)
+{
+  if (bind->bind_axis == axis)
+    return;
+
+  bind->bind_axis = axis;
+
+  update_actor_position (bind);
+
+  g_object_notify (G_OBJECT (bind), "bind-axis");
+}
+
+static void
+_clutter_bind_constraint_set_offset (ClutterBindConstraint *bind,
+                                     gfloat                 offset)
+{
+  if (fabs (bind->offset - offset) < 0.00001f)
+    return;
+
+  bind->offset = offset;
+
+  update_actor_position (bind);
+
+  g_object_notify (G_OBJECT (bind), "offset");
+}
+
+static void
+clutter_bind_constraint_set_property (GObject      *gobject,
+                                      guint         prop_id,
+                                      const GValue *value,
+                                      GParamSpec   *pspec)
+{
+  ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (gobject);
+
+  switch (prop_id)
+    {
+    case PROP_SOURCE:
+      _clutter_bind_constraint_set_source (bind, g_value_get_object (value));
+      break;
+
+    case PROP_BIND_AXIS:
+      _clutter_bind_constraint_set_bind_axis (bind, g_value_get_enum (value));
+      break;
+
+    case PROP_OFFSET:
+      _clutter_bind_constraint_set_offset (bind, g_value_get_float (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+clutter_bind_constraint_get_property (GObject    *gobject,
+                                      guint       prop_id,
+                                      GValue     *value,
+                                      GParamSpec *pspec)
+{
+  ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (gobject);
+
+  switch (prop_id)
+    {
+    case PROP_SOURCE:
+      g_value_set_object (value, bind->source);
+      break;
+
+    case PROP_BIND_AXIS:
+      g_value_set_enum (value, bind->bind_axis);
+      break;
+
+    case PROP_OFFSET:
+      g_value_set_float (value, bind->offset);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+clutter_bind_constraint_class_init (ClutterBindConstraintClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GParamSpec *pspec;
+
+  gobject_class->set_property = clutter_bind_constraint_set_property;
+  gobject_class->get_property = clutter_bind_constraint_get_property;
+
+  pspec = g_param_spec_object ("source",
+                               "Source",
+                               "The source of the binding",
+                               CLUTTER_TYPE_ACTOR,
+                               CLUTTER_PARAM_READWRITE |
+                               G_PARAM_CONSTRUCT);
+  g_object_class_install_property (gobject_class, PROP_SOURCE, pspec);
+
+  pspec = g_param_spec_enum ("bind-axis",
+                             "Bind Axis",
+                             "The axis to bind the position from",
+                             CLUTTER_TYPE_BIND_AXIS,
+                             CLUTTER_BIND_X_AXIS,
+                             CLUTTER_PARAM_READWRITE |
+                             G_PARAM_CONSTRUCT);
+  g_object_class_install_property (gobject_class, PROP_BIND_AXIS, pspec);
+
+  pspec = g_param_spec_float ("offset",
+                              "Offset",
+                              "The offset in pixels to apply to the binding",
+                              -G_MAXFLOAT, G_MAXFLOAT,
+                              0.0f,
+                              CLUTTER_PARAM_READWRITE |
+                              G_PARAM_CONSTRUCT);
+  g_object_class_install_property (gobject_class, PROP_OFFSET, pspec);
+}
+
+static void
+clutter_bind_constraint_init (ClutterBindConstraint *self)
+{
+  self->source = NULL;
+  self->bind_axis = CLUTTER_BIND_X_AXIS;
+  self->offset = 0.0f;
+}
+
+ClutterConstraint *
+clutter_bind_constraint_new (ClutterActor    *source,
+                             ClutterBindAxis  axis,
+                             gfloat           offset)
+{
+  g_return_val_if_fail (CLUTTER_IS_ACTOR (source), NULL);
+
+  return g_object_new (CLUTTER_TYPE_BIND_CONSTRAINT,
+                       "source", source,
+                       "bind-axis", axis,
+                       "offset", offset,
+                       NULL);
+}
diff --git a/clutter/clutter-bind-constraint.h b/clutter/clutter-bind-constraint.h
new file mode 100644 (file)
index 0000000..8aaed18
--- /dev/null
@@ -0,0 +1,32 @@
+#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
+#error "Only <clutter/clutter.h> can be included directly."
+#endif
+
+#ifndef __CLUTTER_BIND_CONSTRAINT_H__
+#define __CLUTTER_BIND_CONSTRAINT_H__
+
+#include <clutter/clutter-constraint.h>
+
+G_BEGIN_DECLS
+
+#define CLUTTER_TYPE_BIND_CONSTRAINT    (clutter_bind_constraint_get_type ())
+#define CLUTTER_BIND_CONSTRAINT(obj)    (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BIND_CONSTRAINT, ClutterBindConstraint))
+#define CLUTTER_IS_BIND_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BIND_CONSTRAINT))
+
+typedef struct _ClutterBindConstraint   ClutterBindConstraint;
+
+typedef enum { /*< prefix=CLUTTER_BIND >*/
+  CLUTTER_BIND_X_AXIS,
+  CLUTTER_BIND_Y_AXIS,
+  CLUTTER_BIND_Z_AXIS
+} ClutterBindAxis;
+
+GType clutter_bind_constraint_get_type (void) G_GNUC_CONST;
+
+ClutterConstraint *clutter_bind_constraint_new (ClutterActor    *source,
+                                                ClutterBindAxis  axis,
+                                                gfloat           offset);
+
+G_END_DECLS
+
+#endif /* __CLUTTER_BIND_CONSTRAINT_H__ */
index 9347e09..ccf7298 100644 (file)
@@ -45,6 +45,7 @@
 #include "clutter-behaviour-path.h"
 #include "clutter-behaviour-rotate.h"
 #include "clutter-behaviour-scale.h"
+#include "clutter-bind-constraint.h"
 #include "clutter-binding-pool.h"
 #include "clutter-bin-layout.h"
 #include "clutter-box.h"