[eog/gestures: 2/4] EogScrollView: add image rotation gesture
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [eog/gestures: 2/4] EogScrollView: add image rotation gesture
- Date: Fri, 23 May 2014 18:07:13 +0000 (UTC)
commit 6682d82afe2051d8a313595404abada5e2d292f6
Author: Carlos Garnacho <carlosg gnome org>
Date: Mon May 5 20:17:43 2014 +0200
EogScrollView: add image rotation gesture
GtkGestureRotate is used to determine angle changes, which are then
used to rotate the image in 90 degree steps. In order to avoid
unintended angle changes when the delta is too close to a switch
point, there is a "grey area" threshold that makes it harder to switch
forth and back again.
This gesture has been added to the same group than the GtkGestureZoom,
as both are meant to share sequences and state.
src/eog-image.c | 1 +
src/eog-scroll-view.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 126 insertions(+), 0 deletions(-)
---
diff --git a/src/eog-image.c b/src/eog-image.c
index b11c8cb..86f216a 100644
--- a/src/eog-image.c
+++ b/src/eog-image.c
@@ -445,6 +445,7 @@ eog_image_real_transform (EogImage *img,
priv->width = gdk_pixbuf_get_width (transformed);
priv->height = gdk_pixbuf_get_height (transformed);
+ eog_image_modified (img);
modified = TRUE;
}
diff --git a/src/eog-scroll-view.c b/src/eog-scroll-view.c
index 0593817..74611df 100644
--- a/src/eog-scroll-view.c
+++ b/src/eog-scroll-view.c
@@ -65,6 +65,14 @@ typedef enum {
EOG_SCROLL_VIEW_CURSOR_DRAG
} EogScrollViewCursor;
+typedef enum {
+ EOG_ROTATION_0,
+ EOG_ROTATION_90,
+ EOG_ROTATION_180,
+ EOG_ROTATION_270,
+ N_EOG_ROTATIONS
+} EogRotationState;
+
/* Drag 'n Drop */
static GtkTargetEntry target_table[] = {
{ "text/uri-list", 0, 0},
@@ -162,7 +170,9 @@ struct _EogScrollViewPrivate {
cairo_surface_t *background_surface;
GtkGesture *zoom_gesture;
+ GtkGesture *rotate_gesture;
gdouble initial_zoom;
+ EogRotationState rotate_state;
};
static void scroll_by (EogScrollView *view, int xofs, int yofs);
@@ -1970,6 +1980,107 @@ zoom_gesture_end_cb (GtkGestureZoom *gesture,
eog_scroll_view_set_cursor (view, EOG_SCROLL_VIEW_CURSOR_NORMAL);
}
+static void
+rotate_gesture_begin_cb (GtkGesture *gesture,
+ GdkEventSequence *sequence,
+ EogScrollView *view)
+{
+ EogScrollViewPrivate *priv;
+
+ priv = view->priv;
+ priv->rotate_state = EOG_TRANSFORM_NONE;
+}
+
+static gboolean
+scroll_view_check_angle (gdouble angle,
+ gdouble min,
+ gdouble max,
+ gdouble threshold)
+{
+ if (min < max) {
+ return (angle > min - threshold &&
+ angle < max + threshold);
+ } else {
+ return (angle < max + threshold ||
+ angle > min - threshold);
+ }
+}
+
+static EogRotationState
+scroll_view_get_rotate_state (EogScrollView *view,
+ gdouble delta)
+{
+ EogScrollViewPrivate *priv;
+
+ priv = view->priv;
+
+#define THRESHOLD (G_PI / 16)
+ switch (priv->rotate_state) {
+ case EOG_ROTATION_0:
+ if (scroll_view_check_angle (delta, G_PI * 7 / 4,
+ G_PI / 4, THRESHOLD))
+ return priv->rotate_state;
+ break;
+ case EOG_ROTATION_90:
+ if (scroll_view_check_angle (delta, G_PI / 4,
+ G_PI * 3 / 4, THRESHOLD))
+ return priv->rotate_state;
+ break;
+ case EOG_ROTATION_180:
+ if (scroll_view_check_angle (delta, G_PI * 3 / 4,
+ G_PI * 5 / 4, THRESHOLD))
+ return priv->rotate_state;
+ break;
+ case EOG_ROTATION_270:
+ if (scroll_view_check_angle (delta, G_PI * 5 / 4,
+ G_PI * 7 / 4, THRESHOLD))
+ return priv->rotate_state;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+#undef THRESHOLD
+
+ if (scroll_view_check_angle (delta, G_PI / 4, G_PI * 3 / 4, 0))
+ return EOG_ROTATION_90;
+ else if (scroll_view_check_angle (delta, G_PI * 3 / 4, G_PI * 5 / 4, 0))
+ return EOG_ROTATION_180;
+ else if (scroll_view_check_angle (delta, G_PI * 5 / 4, G_PI * 7 / 4, 0))
+ return EOG_ROTATION_270;
+
+ return EOG_ROTATION_0;
+}
+
+static void
+rotate_gesture_angle_changed_cb (GtkGestureRotate *rotate,
+ gdouble angle,
+ gdouble delta,
+ EogScrollView *view)
+{
+ EogRotationState rotate_state;
+ EogScrollViewPrivate *priv;
+ gint angle_diffs [N_EOG_ROTATIONS][N_EOG_ROTATIONS] = {
+ { 0, 90, 180, 270 },
+ { 270, 0, 90, 180 },
+ { 180, 270, 0, 90 },
+ { 90, 180, 270, 0 }
+ };
+ gint rotate_angle;
+
+ priv = view->priv;
+ rotate_state = scroll_view_get_rotate_state (view, delta);
+
+ if (priv->rotate_state == rotate_state)
+ return;
+
+ rotate_angle = angle_diffs[priv->rotate_state][rotate_state];
+ eog_image_transform (priv->image,
+ eog_transform_rotate_new (rotate_angle),
+ NULL);
+ priv->rotate_state = rotate_state;
+}
+
/*==================================
image loading callbacks
@@ -2633,6 +2744,14 @@ eog_scroll_view_init (EogScrollView *view)
g_signal_connect (priv->zoom_gesture, "cancel",
G_CALLBACK (zoom_gesture_end_cb), view);
gtk_gesture_attach (priv->zoom_gesture, GTK_PHASE_CAPTURE);
+
+ priv->rotate_gesture = gtk_gesture_rotate_new (GTK_WIDGET (view));
+ gtk_gesture_group (priv->rotate_gesture, priv->zoom_gesture);
+ g_signal_connect (priv->rotate_gesture, "angle-changed",
+ G_CALLBACK (rotate_gesture_angle_changed_cb), view);
+ g_signal_connect (priv->rotate_gesture, "begin",
+ G_CALLBACK (rotate_gesture_begin_cb), view);
+ gtk_gesture_attach (priv->rotate_gesture, GTK_PHASE_CAPTURE);
}
static void
@@ -2681,6 +2800,12 @@ eog_scroll_view_dispose (GObject *object)
priv->zoom_gesture = NULL;
}
+ if (priv->rotate_gesture) {
+ gtk_gesture_detach (priv->rotate_gesture);
+ g_object_unref (priv->rotate_gesture);
+ priv->rotate_gesture = NULL;
+ }
+
G_OBJECT_CLASS (eog_scroll_view_parent_class)->dispose (object);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]