[gtk+/gestures: 88/140] Add GtkGesturePan



commit 42f2865c3488558068d9e8a4f4d63bde5ff35029
Author: Carlos Garnacho <carlosg gnome org>
Date:   Tue Apr 8 21:21:56 2014 +0200

    Add GtkGesturePan
    
    This gesture reports events on horizontal/vertical panning gestures.

 gtk/Makefile.am     |    2 +
 gtk/gtk.h           |    1 +
 gtk/gtkenums.h      |   14 +++
 gtk/gtkgesturepan.c |  274 +++++++++++++++++++++++++++++++++++++++++++++++++++
 gtk/gtkgesturepan.h |   75 ++++++++++++++
 5 files changed, 366 insertions(+), 0 deletions(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 97ab70d..cb29951 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -279,6 +279,7 @@ gtk_public_h_sources =              \
        gtkgesturedrag.h        \
        gtkgesturelongpress.h   \
        gtkgesturemultipress.h  \
+       gtkgesturepan.h         \
        gtkgesturerotate.h      \
        gtkgesturesingle.h      \
        gtkgestureswipe.h       \
@@ -775,6 +776,7 @@ gtk_base_c_sources =                \
        gtkgesturedrag.c        \
        gtkgesturelongpress.c   \
        gtkgesturemultipress.c  \
+       gtkgesturepan.c         \
        gtkgesturerotate.c      \
        gtkgesturesingle.c      \
        gtkgestureswipe.c       \
diff --git a/gtk/gtk.h b/gtk/gtk.h
index df48bec..19e4b73 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -111,6 +111,7 @@
 #include <gtk/gtkgesturedrag.h>
 #include <gtk/gtkgesturelongpress.h>
 #include <gtk/gtkgesturemultipress.h>
+#include <gtk/gtkgesturepan.h>
 #include <gtk/gtkgesturerotate.h>
 #include <gtk/gtkgesturesingle.h>
 #include <gtk/gtkgestureswipe.h>
diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h
index fdb58f4..073db5d 100644
--- a/gtk/gtkenums.h
+++ b/gtk/gtkenums.h
@@ -1280,4 +1280,18 @@ typedef enum
   GTK_EVENT_SEQUENCE_DENIED
 } GtkEventSequenceState;
 
+typedef enum
+{
+  GTK_PAN_DIRECTION_LEFT,
+  GTK_PAN_DIRECTION_RIGHT,
+  GTK_PAN_DIRECTION_UP,
+  GTK_PAN_DIRECTION_DOWN
+} GtkPanDirection;
+
+typedef enum
+{
+  GTK_PAN_ORIENTATION_VERTICAL,
+  GTK_PAN_ORIENTATION_HORIZONTAL
+} GtkPanOrientation;
+
 #endif /* __GTK_ENUMS_H__ */
diff --git a/gtk/gtkgesturepan.c b/gtk/gtkgesturepan.c
new file mode 100644
index 0000000..5f4eb3d
--- /dev/null
+++ b/gtk/gtkgesturepan.c
@@ -0,0 +1,274 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2014, Red Hat, Inc.
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s): Carlos Garnacho <carlosg gnome org>
+ */
+#include "config.h"
+#include <gtk/gtkgesturepan.h>
+#include "gtktypebuiltins.h"
+#include "gtkprivate.h"
+#include "gtkintl.h"
+
+typedef struct _GtkGesturePanPrivate GtkGesturePanPrivate;
+
+struct _GtkGesturePanPrivate
+{
+  guint orientation : 2;
+  guint panning     : 1;
+};
+
+enum {
+  PROP_ORIENTATION = 1
+};
+
+enum {
+  PAN,
+  N_SIGNALS
+};
+
+static guint signals[N_SIGNALS] = { 0 };
+
+G_DEFINE_TYPE (GtkGesturePan, gtk_gesture_pan, GTK_TYPE_GESTURE_DRAG)
+
+static void
+gtk_gesture_pan_get_property (GObject    *object,
+                              guint       prop_id,
+                              GValue     *value,
+                              GParamSpec *pspec)
+{
+  GtkGesturePanPrivate *priv;
+
+  priv = gtk_gesture_pan_get_instance_private (GTK_GESTURE_PAN (object));
+
+  switch (prop_id)
+    {
+    case PROP_ORIENTATION:
+      g_value_set_enum (value, priv->orientation);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtk_gesture_pan_set_property (GObject      *object,
+                              guint         prop_id,
+                              const GValue *value,
+                              GParamSpec   *pspec)
+{
+  switch (prop_id)
+    {
+    case PROP_ORIENTATION:
+      gtk_gesture_pan_set_orientation (GTK_GESTURE_PAN (object),
+                                       g_value_get_enum (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+direction_from_offset (gdouble            offset_x,
+                       gdouble            offset_y,
+                       GtkPanOrientation  orientation,
+                       GtkPanDirection   *direction)
+{
+  if (orientation == GTK_PAN_ORIENTATION_HORIZONTAL)
+    {
+      if (offset_x > 0)
+        *direction = GTK_PAN_DIRECTION_RIGHT;
+      else
+        *direction = GTK_PAN_DIRECTION_LEFT;
+    }
+  else if (orientation == GTK_PAN_ORIENTATION_VERTICAL)
+    {
+      if (offset_y > 0)
+        *direction = GTK_PAN_DIRECTION_DOWN;
+      else
+        *direction = GTK_PAN_DIRECTION_UP;
+    }
+  else
+    g_assert_not_reached ();
+}
+
+static gboolean
+guess_direction (GtkGesturePan   *gesture,
+                 gdouble          offset_x,
+                 gdouble          offset_y,
+                 GtkPanDirection *direction)
+{
+  gdouble abs_x, abs_y;
+
+  abs_x = ABS (offset_x);
+  abs_y = ABS (offset_y);
+
+#define FACTOR 3
+  if (abs_x > abs_y * FACTOR)
+    direction_from_offset (offset_x, offset_y,
+                           GTK_PAN_ORIENTATION_HORIZONTAL, direction);
+  else if (abs_y > abs_x * FACTOR)
+    direction_from_offset (offset_x, offset_y,
+                           GTK_PAN_ORIENTATION_VERTICAL, direction);
+  else
+    return FALSE;
+
+  return TRUE;
+#undef FACTOR
+}
+
+static gboolean
+check_orientation_matches (GtkGesturePan   *gesture,
+                           GtkPanDirection  direction)
+{
+  GtkGesturePanPrivate *priv = gtk_gesture_pan_get_instance_private (gesture);
+
+  if (priv->orientation == 0)
+    return FALSE;
+
+  return (((direction == GTK_PAN_DIRECTION_LEFT ||
+            direction == GTK_PAN_DIRECTION_RIGHT) &&
+           priv->orientation == GTK_PAN_ORIENTATION_HORIZONTAL) ||
+          ((direction == GTK_PAN_DIRECTION_UP ||
+            direction == GTK_PAN_DIRECTION_DOWN) &&
+           priv->orientation == GTK_PAN_ORIENTATION_VERTICAL));
+}
+
+static void
+gtk_gesture_pan_drag_update (GtkGestureDrag *gesture,
+                             gdouble         offset_x,
+                             gdouble         offset_y)
+{
+  GtkGesturePanPrivate *priv;
+  GtkPanDirection direction;
+  GtkGesturePan *pan;
+  gdouble offset;
+
+  pan = GTK_GESTURE_PAN (gesture);
+  priv = gtk_gesture_pan_get_instance_private (pan);
+
+  if (!priv->panning)
+    {
+      if (!guess_direction (pan, offset_x, offset_y, &direction))
+        return;
+
+      if (!check_orientation_matches (pan, direction))
+        {
+          gtk_gesture_set_state (GTK_GESTURE (gesture),
+                                 GTK_EVENT_SEQUENCE_DENIED);
+          return;
+        }
+
+      priv->panning = TRUE;
+    }
+  else
+    direction_from_offset (offset_x, offset_y, priv->orientation, &direction);
+
+  offset = (priv->orientation == GTK_PAN_ORIENTATION_VERTICAL) ?
+    ABS (offset_y) : ABS (offset_x);
+  g_signal_emit (gesture, signals[PAN], 0, direction, offset);
+}
+
+static void
+gtk_gesture_pan_drag_end (GtkGestureDrag *gesture,
+                          gdouble         offset_x,
+                          gdouble         offset_y)
+{
+  GtkGesturePanPrivate *priv;
+
+  priv = gtk_gesture_pan_get_instance_private (GTK_GESTURE_PAN (gesture));
+  priv->panning = FALSE;
+}
+
+static void
+gtk_gesture_pan_class_init (GtkGesturePanClass *klass)
+{
+  GtkGestureDragClass *drag_gesture_class = GTK_GESTURE_DRAG_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->get_property = gtk_gesture_pan_get_property;
+  object_class->set_property = gtk_gesture_pan_set_property;
+
+  drag_gesture_class->drag_update = gtk_gesture_pan_drag_update;
+  drag_gesture_class->drag_end = gtk_gesture_pan_drag_end;
+
+  g_object_class_install_property (object_class,
+                                   PROP_ORIENTATION,
+                                   g_param_spec_enum ("orientation",
+                                                      P_("Orientation"),
+                                                      P_("Allowed orientations"),
+                                                      GTK_TYPE_PAN_ORIENTATION,
+                                                      GTK_PAN_ORIENTATION_HORIZONTAL,
+                                                      GTK_PARAM_READWRITE));
+  signals[PAN] =
+    g_signal_new ("pan",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GtkGesturePanClass, pan),
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 1, GTK_TYPE_PAN_DIRECTION);
+}
+
+static void
+gtk_gesture_pan_init (GtkGesturePan *gesture)
+{
+  GtkGesturePanPrivate *priv;
+
+  priv = gtk_gesture_pan_get_instance_private (gesture);
+  priv->orientation = GTK_PAN_ORIENTATION_HORIZONTAL;
+}
+
+GtkGesture *
+gtk_gesture_pan_new (GtkWidget         *widget,
+                     GtkPanOrientation  orientation)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+  return g_object_new (GTK_TYPE_GESTURE_PAN,
+                       "widget", widget,
+                       "orientation", orientation,
+                       NULL);
+}
+
+GtkPanOrientation
+gtk_gesture_pan_get_orientation (GtkGesturePan *gesture)
+{
+  GtkGesturePanPrivate *priv;
+
+  g_return_val_if_fail (GTK_IS_GESTURE_PAN (gesture), 0);
+
+  priv = gtk_gesture_pan_get_instance_private (gesture);
+
+  return priv->orientation;
+}
+
+void
+gtk_gesture_pan_set_orientation (GtkGesturePan     *gesture,
+                                 GtkPanOrientation  orientation)
+{
+  GtkGesturePanPrivate *priv;
+
+  g_return_if_fail (GTK_IS_GESTURE_PAN (gesture));
+  g_return_if_fail (orientation == GTK_PAN_ORIENTATION_HORIZONTAL ||
+                    orientation == GTK_PAN_ORIENTATION_VERTICAL);
+
+  priv = gtk_gesture_pan_get_instance_private (gesture);
+
+  if (priv->orientation == orientation)
+    return;
+
+  priv->orientation = orientation;
+  g_object_notify (G_OBJECT (gesture), "orientation");
+}
diff --git a/gtk/gtkgesturepan.h b/gtk/gtkgesturepan.h
new file mode 100644
index 0000000..fdbde4e
--- /dev/null
+++ b/gtk/gtkgesturepan.h
@@ -0,0 +1,75 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2014, Red Hat, Inc.
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author(s): Carlos Garnacho <carlosg gnome org>
+ */
+#ifndef __GTK_GESTURE_PAN_H__
+#define __GTK_GESTURE_PAN_H__
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gtk/gtkenums.h>
+#include <gtk/gtkgesturedrag.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_GESTURE_PAN         (gtk_gesture_pan_get_type ())
+#define GTK_GESTURE_PAN(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_GESTURE_PAN, GtkGesturePan))
+#define GTK_GESTURE_PAN_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_GESTURE_PAN, 
GtkGesturePanClass))
+#define GTK_IS_GESTURE_PAN(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_GESTURE_PAN))
+#define GTK_IS_GESTURE_PAN_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_GESTURE_PAN))
+#define GTK_GESTURE_PAN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_GESTURE_PAN, 
GtkGesturePanClass))
+
+typedef struct _GtkGesturePan GtkGesturePan;
+typedef struct _GtkGesturePanClass GtkGesturePanClass;
+
+struct _GtkGesturePan
+{
+  GtkGestureDrag parent_instance;
+};
+
+struct _GtkGesturePanClass
+{
+  GtkGestureDragClass parent_class;
+
+  void (* pan) (GtkGesturePan *gesture,
+                GtkPanDirection direction,
+                gdouble         offset);
+
+  /*< private >*/
+  gpointer padding[10];
+};
+
+GDK_AVAILABLE_IN_3_14
+GType             gtk_gesture_pan_get_type        (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_3_14
+GtkGesture *      gtk_gesture_pan_new             (GtkWidget         *widget,
+                                                   GtkPanOrientation  orientation);
+
+GDK_AVAILABLE_IN_3_14
+GtkPanOrientation gtk_gesture_pan_get_orientation (GtkGesturePan     *gesture);
+
+GDK_AVAILABLE_IN_3_14
+void              gtk_gesture_pan_set_orientation (GtkGesturePan     *gesture,
+                                                   GtkPanOrientation  orientation);
+
+
+G_END_DECLS
+
+#endif /* __GTK_GESTURE_PAN_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]