[gnome-photos/wip/rishi/zoom: 4/7] preview-view: Use scroll-events to zoom, mouse movements for panning
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-photos/wip/rishi/zoom: 4/7] preview-view: Use scroll-events to zoom, mouse movements for panning
- Date: Tue, 6 Jun 2017 17:13:51 +0000 (UTC)
commit a27009ae2ea20b249253208815f68c086f43b67e
Author: Debarshi Ray <debarshir gnome org>
Date: Wed Mar 29 11:03:39 2017 +0200
preview-view: Use scroll-events to zoom, mouse movements for panning
Scrolling uses a smaller zoom factor compared to keyboard accelerators.
A user is more likely to scroll by a bigger delta as compared to
repeatedly pressing the accelerator keys.
https://bugzilla.gnome.org/show_bug.cgi?id=742662
src/photos-preview-view.c | 186 +++++++++++++++++++++++++++++++++++++++++----
1 files changed, 170 insertions(+), 16 deletions(-)
---
diff --git a/src/photos-preview-view.c b/src/photos-preview-view.c
index 11990d4..7e7136b 100644
--- a/src/photos-preview-view.c
+++ b/src/photos-preview-view.c
@@ -25,6 +25,8 @@
#include "config.h"
+#include <math.h>
+
#include <glib.h>
#include <gio/gio.h>
#include <glib/gi18n.h>
@@ -57,6 +59,9 @@ struct _PhotosPreviewView
PhotosModeController *mode_cntrlr;
PhotosPreviewNavButtons *nav_buttons;
PhotosTool *current_tool;
+ gboolean grabbed;
+ gdouble event_x_last;
+ gdouble event_y_last;
gdouble zoom_best_fit;
};
@@ -77,6 +82,7 @@ G_DEFINE_TYPE (PhotosPreviewView, photos_preview_view, GTK_TYPE_BIN);
static const gdouble ZOOM_FACTOR_1 = 2.8561;
static const gdouble ZOOM_FACTOR_2 = 1.69;
+static const gdouble ZOOM_FACTOR_3 = 1.3;
static GtkWidget *photos_preview_view_create_view_with_container (PhotosPreviewView *self);
@@ -111,17 +117,53 @@ photos_preview_view_button_press_event (GtkWidget *widget, GdkEvent *event, gpoi
current_view = photos_preview_view_get_view_from_view_container (current_view_container);
g_return_val_if_fail (widget == current_view, GDK_EVENT_PROPAGATE);
- if (self->current_tool == NULL)
+ if (self->node == NULL)
goto out;
- switch (event->button.button)
+ if (self->current_tool == NULL)
{
- case 1:
- ret_val = photos_tool_left_click_event (self->current_tool, &(event->button));
- break;
+ switch (event->button.button)
+ {
+ case 1:
+ {
+ if (photos_utils_scrolled_window_can_scroll (GTK_SCROLLED_WINDOW (current_view_container)))
+ {
+ GdkCursor *cursor = NULL;
+ GdkDisplay *display;
+ GdkWindow *window;
- default:
- break;
+ window = gtk_widget_get_window (widget);
+ display = gdk_window_get_display (window);
+ cursor = gdk_cursor_new_for_display (display, GDK_FLEUR);
+ gdk_window_set_cursor (window, cursor);
+
+ self->grabbed = TRUE;
+ self->event_x_last = event->button.x;
+ self->event_y_last = event->button.y;
+
+ ret_val = GDK_EVENT_STOP;
+
+ g_object_unref (cursor);
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch (event->button.button)
+ {
+ case 1:
+ ret_val = photos_tool_left_click_event (self->current_tool, &(event->button));
+ break;
+
+ default:
+ break;
+ }
}
out:
@@ -141,17 +183,43 @@ photos_preview_view_button_release_event (GtkWidget *widget, GdkEvent *event, gp
current_view = photos_preview_view_get_view_from_view_container (current_view_container);
g_return_val_if_fail (widget == current_view, GDK_EVENT_PROPAGATE);
- if (self->current_tool == NULL)
+ if (self->node == NULL)
goto out;
- switch (event->button.button)
+ if (self->current_tool == NULL)
{
- case 1:
- ret_val = photos_tool_left_unclick_event (self->current_tool, &(event->button));
- break;
+ if (!self->grabbed)
+ goto out;
- default:
- break;
+ switch (event->button.button)
+ {
+ case 1:
+ {
+ GdkWindow *window;
+
+ window = gtk_widget_get_window (widget);
+ gdk_window_set_cursor (window, NULL);
+ self->grabbed = FALSE;
+ self->event_x_last = -1.0;
+ self->event_y_last = -1.0;
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch (event->button.button)
+ {
+ case 1:
+ ret_val = photos_tool_left_unclick_event (self->current_tool, &(event->button));
+ break;
+
+ default:
+ break;
+ }
}
out:
@@ -227,10 +295,32 @@ photos_preview_view_motion_notify_event (GtkWidget *widget, GdkEvent *event, gpo
current_view = photos_preview_view_get_view_from_view_container (current_view_container);
g_return_val_if_fail (widget == current_view, GDK_EVENT_PROPAGATE);
- if (self->current_tool == NULL)
+ if (self->node == NULL)
goto out;
- ret_val = photos_tool_motion_event (self->current_tool, &(event->motion));
+ if (self->current_tool == NULL)
+ {
+ if (self->grabbed)
+ {
+ gdouble delta_x;
+ gdouble delta_y;
+
+ /* We are moving the content, not the view. Hence the
+ * deltas are inverted.
+ */
+ delta_x = self->event_x_last - event->motion.x;
+ delta_y = self->event_y_last - event->motion.y;
+
+ self->event_x_last = event->motion.x;
+ self->event_y_last = event->motion.y;
+
+ photos_utils_scrolled_window_scroll (GTK_SCROLLED_WINDOW (current_view_container), delta_x,
delta_y);
+ }
+ }
+ else
+ {
+ ret_val = photos_tool_motion_event (self->current_tool, &(event->motion));
+ }
out:
return ret_val;
@@ -316,6 +406,66 @@ photos_preview_view_navigate_previous (PhotosPreviewView *self)
}
+static gboolean
+photos_preview_view_scroll_event (GtkWidget *widget, GdkEvent *event, gpointer user_data)
+{
+ PhotosPreviewView *self = PHOTOS_PREVIEW_VIEW (user_data);
+ GtkWidget *current_view;
+ GtkWidget *current_view_container;
+ gboolean best_fit;
+ gboolean ret_val = GDK_EVENT_PROPAGATE;
+ gdouble delta_abs;
+ gdouble zoom;
+ gdouble zoom_factor;
+ gdouble zoom_factor_for_delta;
+
+ current_view_container = gtk_stack_get_visible_child (GTK_STACK (self->stack));
+ current_view = photos_preview_view_get_view_from_view_container (current_view_container);
+ g_return_val_if_fail (widget == current_view, GDK_EVENT_PROPAGATE);
+
+ if (self->node == NULL)
+ goto out;
+
+ if ((event->scroll.state & GDK_SHIFT_MASK) != 0 || (event->scroll.state & GDK_CONTROL_MASK) != 0)
+ goto out;
+
+ best_fit = photos_image_view_get_best_fit (PHOTOS_IMAGE_VIEW (widget));
+ zoom_factor = best_fit && event->scroll.delta_y < 0.0 ? ZOOM_FACTOR_2 : ZOOM_FACTOR_3;
+
+ delta_abs = fabs (event->scroll.delta_y);
+ zoom_factor_for_delta = pow (zoom_factor, delta_abs);
+
+ zoom = photos_image_view_get_zoom (PHOTOS_IMAGE_VIEW (widget));
+
+ if (event->scroll.delta_y < 0.0)
+ {
+ zoom *= zoom_factor_for_delta;
+ photos_image_view_set_zoom (PHOTOS_IMAGE_VIEW (widget), zoom);
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (self->zoom_best_fit_action), TRUE);
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (self->zoom_out_action), TRUE);
+ }
+ else
+ {
+ zoom /= zoom_factor_for_delta;
+ if (zoom < self->zoom_best_fit || photos_utils_equal_double (self->zoom_best_fit, zoom))
+ {
+ photos_image_view_set_best_fit (PHOTOS_IMAGE_VIEW (widget), TRUE);
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (self->zoom_best_fit_action), FALSE);
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (self->zoom_out_action), FALSE);
+ }
+ else
+ {
+ photos_image_view_set_zoom (PHOTOS_IMAGE_VIEW (widget), zoom);
+ }
+ }
+
+ ret_val = GDK_EVENT_STOP;
+
+ out:
+ return ret_val;
+}
+
+
static GtkWidget *
photos_preview_view_create_view_with_container (PhotosPreviewView *self)
{
@@ -337,6 +487,7 @@ photos_preview_view_create_view_with_container (PhotosPreviewView *self)
g_signal_connect (view, "motion-notify-event", G_CALLBACK (photos_preview_view_motion_notify_event), self);
g_signal_connect (view, "notify::best-fit", G_CALLBACK (photos_preview_view_notify_best_fit), self);
g_signal_connect (view, "notify::zoom", G_CALLBACK (photos_preview_view_notify_zoom), self);
+ g_signal_connect (view, "scroll-event", G_CALLBACK (photos_preview_view_scroll_event), self);
/* It has to be visible to become the visible child of self->stack. */
gtk_widget_show_all (sw);
@@ -951,6 +1102,9 @@ photos_preview_view_init (PhotosPreviewView *self)
G_CALLBACK (photos_preview_view_zoom_out),
self,
G_CONNECT_SWAPPED);
+
+ self->event_x_last = -1.0;
+ self->event_y_last = -1.0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]