[gnome-photos/wip/rishi/zoom: 5/5] application, help-overlay, preview-view: Hook up zooming to GActions
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-photos/wip/rishi/zoom: 5/5] application, help-overlay, preview-view: Hook up zooming to GActions
- Date: Tue, 16 May 2017 11:44:48 +0000 (UTC)
commit c168e12c119c739b54b3b46d78f3482044d92c84
Author: Debarshi Ray <debarshir gnome org>
Date: Wed Mar 29 11:03:39 2017 +0200
application, help-overlay, preview-view: Hook up zooming to GActions
https://bugzilla.gnome.org/show_bug.cgi?id=742662
src/photos-application.c | 25 ++++++
src/photos-help-overlay.ui | 21 +++++
src/photos-preview-view.c | 191 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 237 insertions(+), 0 deletions(-)
---
diff --git a/src/photos-application.c b/src/photos-application.c
index 35505c4..f58416c 100644
--- a/src/photos-application.c
+++ b/src/photos-application.c
@@ -111,6 +111,9 @@ struct _PhotosApplication
GSimpleAction *set_ss_action;
GSimpleAction *share_action;
GSimpleAction *sharpen_action;
+ GSimpleAction *zoom_best_fit_action;
+ GSimpleAction *zoom_in_action;
+ GSimpleAction *zoom_out_action;
GtkWidget *main_window;
PhotosBaseManager *shr_pnt_mngr;
PhotosCameraCache *camera_cache;
@@ -337,6 +340,9 @@ photos_application_actions_update (PhotosApplication *self)
selection = photos_selection_controller_get_selection (self->sel_cntrlr);
selection_mode = photos_utils_get_selection_mode ();
+ g_simple_action_set_enabled (self->zoom_best_fit_action, FALSE);
+ g_simple_action_set_enabled (self->zoom_out_action, FALSE);
+
enable = (mode == PHOTOS_WINDOW_MODE_EDIT);
g_simple_action_set_enabled (self->blacks_exposure_action, enable);
g_simple_action_set_enabled (self->brightness_contrast_action, enable);
@@ -367,6 +373,7 @@ photos_application_actions_update (PhotosApplication *self)
g_simple_action_set_enabled (self->gear_action, enable);
g_simple_action_set_enabled (self->set_bg_action, enable);
g_simple_action_set_enabled (self->set_ss_action, enable);
+ g_simple_action_set_enabled (self->zoom_in_action, enable);
enable = ((load_state == PHOTOS_LOAD_STATE_FINISHED && mode == PHOTOS_WINDOW_MODE_PREVIEW)
|| (selection_mode && item != NULL));
@@ -1689,6 +1696,9 @@ photos_application_startup (GApplication *application)
const gchar *save_accels[2] = {"<Primary>x", NULL};
const gchar *search_accels[2] = {"<Primary>f", NULL};
const gchar *select_all_accels[2] = {"<Primary>a", NULL};
+ const gchar *zoom_best_fit_accels[3] = {"<Primary>0", NULL};
+ const gchar *zoom_in_accels[3] = {"<Primary>plus", "<Primary>equal", NULL};
+ const gchar *zoom_out_accels[2] = {"<Primary>minus", NULL};
G_APPLICATION_CLASS (photos_application_parent_class)->startup (application);
@@ -1901,6 +1911,15 @@ photos_application_startup (GApplication *application)
self->sharpen_action = g_simple_action_new ("sharpen-current", G_VARIANT_TYPE_DOUBLE);
g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (self->sharpen_action));
+ self->zoom_best_fit_action = g_simple_action_new ("zoom-best-fit", NULL);
+ g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (self->zoom_best_fit_action));
+
+ self->zoom_in_action = g_simple_action_new ("zoom-in", NULL);
+ g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (self->zoom_in_action));
+
+ self->zoom_out_action = g_simple_action_new ("zoom-out", NULL);
+ g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (self->zoom_out_action));
+
g_signal_connect_swapped (self->state->mode_cntrlr,
"window-mode-changed",
G_CALLBACK (photos_application_window_mode_changed),
@@ -1921,6 +1940,9 @@ photos_application_startup (GApplication *application)
gtk_application_set_accels_for_action (GTK_APPLICATION (self), "app.save-current", save_accels);
gtk_application_set_accels_for_action (GTK_APPLICATION (self), "app.search", search_accels);
gtk_application_set_accels_for_action (GTK_APPLICATION (self), "app.select-all", select_all_accels);
+ gtk_application_set_accels_for_action (GTK_APPLICATION (self), "app.zoom-best-fit", zoom_best_fit_accels);
+ gtk_application_set_accels_for_action (GTK_APPLICATION (self), "app.zoom-in", zoom_in_accels);
+ gtk_application_set_accels_for_action (GTK_APPLICATION (self), "app.zoom-out", zoom_out_accels);
g_signal_connect_swapped (self->state->item_mngr,
"load-finished",
@@ -1995,6 +2017,9 @@ photos_application_dispose (GObject *object)
g_clear_object (&self->set_ss_action);
g_clear_object (&self->share_action);
g_clear_object (&self->sharpen_action);
+ g_clear_object (&self->zoom_best_fit_action);
+ g_clear_object (&self->zoom_in_action);
+ g_clear_object (&self->zoom_out_action);
g_clear_object (&self->shr_pnt_mngr);
g_clear_object (&self->camera_cache);
g_clear_object (&self->sel_cntrlr);
diff --git a/src/photos-help-overlay.ui b/src/photos-help-overlay.ui
index 5f00de8..ff09da7 100644
--- a/src/photos-help-overlay.ui
+++ b/src/photos-help-overlay.ui
@@ -146,6 +146,27 @@
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
+ <property name="title" translatable="yes" context="shortcut window">Zoom in</property>
+ <property name="accelerator"><Primary>plus</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkShortcutsShortcut">
+ <property name="visible">1</property>
+ <property name="title" translatable="yes" context="shortcut window">Zoom out</property>
+ <property name="accelerator"><Primary>minus</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkShortcutsShortcut">
+ <property name="visible">1</property>
+ <property name="title" translatable="yes" context="shortcut window">Best fit</property>
+ <property name="accelerator"><Primary>0</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkShortcutsShortcut">
+ <property name="visible">1</property>
<property name="title" translatable="yes" context="shortcut window">Delete</property>
<property name="accelerator">Delete</property>
</object>
diff --git a/src/photos-preview-view.c b/src/photos-preview-view.c
index 220efb2..f1e9dd0 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>
@@ -44,6 +46,8 @@
struct _PhotosPreviewView
{
GtkBin parent_instance;
+ GAction *zoom_best_fit_action;
+ GAction *zoom_out_action;
GCancellable *cancellable;
GeglNode *node;
GtkWidget *overlay;
@@ -54,6 +58,7 @@ struct _PhotosPreviewView
PhotosModeController *mode_cntrlr;
PhotosPreviewNavButtons *nav_buttons;
PhotosTool *current_tool;
+ gdouble zoom_best_fit;
};
struct _PhotosPreviewViewClass
@@ -71,6 +76,9 @@ enum
G_DEFINE_TYPE (PhotosPreviewView, photos_preview_view, GTK_TYPE_BIN);
+static const gdouble ZOOM_FACTOR = 1.20;
+
+
static GtkWidget *photos_preview_view_create_view_with_container (PhotosPreviewView *self);
@@ -209,9 +217,49 @@ photos_preview_view_motion_notify_event (PhotosPreviewView *self, GdkEvent *even
static void
+photos_preview_view_update_zoom_best_fit (PhotosPreviewView *self, PhotosImageView *view)
+{
+ GtkWidget *current_view;
+ GtkWidget *current_view_container;
+ gdouble zoom;
+
+ 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_if_fail (view == PHOTOS_IMAGE_VIEW (current_view));
+
+ zoom = photos_image_view_get_zoom (view);
+ if (!photos_image_view_get_best_fit (view) || zoom == 0.0)
+ return;
+
+ self->zoom_best_fit = zoom;
+}
+
+
+static void
+photos_preview_view_notify_best_fit (GObject *object, GParamSpec *pspec, gpointer user_data)
+{
+ PhotosPreviewView *self = PHOTOS_PREVIEW_VIEW (user_data);
+ PhotosImageView *view = PHOTOS_IMAGE_VIEW (object);
+
+ photos_preview_view_update_zoom_best_fit (self, view);
+}
+
+
+static void
+photos_preview_view_notify_zoom (GObject *object, GParamSpec *pspec, gpointer user_data)
+{
+ PhotosPreviewView *self = PHOTOS_PREVIEW_VIEW (user_data);
+ PhotosImageView *view = PHOTOS_IMAGE_VIEW (object);
+
+ photos_preview_view_update_zoom_best_fit (self, view);
+}
+
+
+static void
photos_preview_view_navigate (PhotosPreviewView *self, gint position)
{
GeglNode *node;
+ //GtkWidget *current_view;
GtkWidget *current_view_container;
GtkWidget *new_view_container;
GtkWidget *next_view;
@@ -227,6 +275,9 @@ photos_preview_view_navigate (PhotosPreviewView *self, gint position)
gtk_stack_set_visible_child (GTK_STACK (self->stack), next_view_container);
+ //current_view = photos_preview_view_get_view_from_view_container (current_view_container);
+ //g_signal_handlers_disconnect_by_func (current_view, photos_preview_view_notify_best_fit, self);
+ //g_signal_handlers_disconnect_by_func (current_view, photos_preview_view_notify_zoom, self);
gtk_container_remove (GTK_CONTAINER (self->stack), current_view_container);
new_view_container = photos_preview_view_create_view_with_container (self);
@@ -248,6 +299,61 @@ 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 ret_val = GDK_EVENT_PROPAGATE;
+ gdouble delta_abs;
+ gdouble zoom;
+ gdouble zoom_factor;
+
+ 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 || event->scroll.state & GDK_CONTROL_MASK)
+ goto out;
+
+ delta_abs = fabs (event->scroll.delta_y);
+ zoom_factor = 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;
+ 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;
+ if (zoom <= self->zoom_best_fit)
+ {
+ 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)
{
@@ -270,6 +376,9 @@ photos_preview_view_create_view_with_container (PhotosPreviewView *self)
g_signal_connect_swapped (view, "motion-notify-event", G_CALLBACK
(photos_preview_view_motion_notify_event), self);
g_signal_connect_swapped (view, "draw-background", G_CALLBACK (photos_preview_view_draw_background), self);
g_signal_connect_swapped (view, "draw-overlay", G_CALLBACK (photos_preview_view_draw_overlay), 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);
@@ -645,6 +754,70 @@ photos_preview_view_window_mode_changed (PhotosPreviewView *self, PhotosWindowMo
static void
+photos_preview_view_zoom_best_fit (PhotosPreviewView *self)
+{
+ GtkWidget *view;
+ GtkWidget *view_container;
+
+ view_container = gtk_stack_get_visible_child (GTK_STACK (self->stack));
+ view = photos_preview_view_get_view_from_view_container (view_container);
+ photos_image_view_set_best_fit (PHOTOS_IMAGE_VIEW (view), 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);
+}
+
+
+static void
+photos_preview_view_zoom_in (PhotosPreviewView *self)
+{
+ GtkWidget *view;
+ GtkWidget *view_container;
+ gdouble zoom;
+
+ g_return_if_fail (self->zoom_best_fit > 0.0);
+
+ view_container = gtk_stack_get_visible_child (GTK_STACK (self->stack));
+ view = photos_preview_view_get_view_from_view_container (view_container);
+
+ zoom = photos_image_view_get_zoom (PHOTOS_IMAGE_VIEW (view));
+ zoom *= ZOOM_FACTOR;
+
+ photos_image_view_set_zoom (PHOTOS_IMAGE_VIEW (view), 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);
+}
+
+
+static void
+photos_preview_view_zoom_out (PhotosPreviewView *self)
+{
+ GtkWidget *view;
+ GtkWidget *view_container;
+ gdouble zoom;
+
+ g_return_if_fail (self->zoom_best_fit > 0.0);
+
+ view_container = gtk_stack_get_visible_child (GTK_STACK (self->stack));
+ view = photos_preview_view_get_view_from_view_container (view_container);
+
+ zoom = photos_image_view_get_zoom (PHOTOS_IMAGE_VIEW (view));
+ zoom /= ZOOM_FACTOR;
+
+ if (zoom <= self->zoom_best_fit)
+ {
+ photos_image_view_set_best_fit (PHOTOS_IMAGE_VIEW (view), 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 (view), zoom);
+ }
+}
+
+
+static void
photos_preview_view_dispose (GObject *object)
{
PhotosPreviewView *self = PHOTOS_PREVIEW_VIEW (object);
@@ -798,6 +971,23 @@ photos_preview_view_init (PhotosPreviewView *self)
action = g_action_map_lookup_action (G_ACTION_MAP (app), "sharpen-current");
g_signal_connect_object (action, "activate", G_CALLBACK (photos_preview_view_sharpen), self,
G_CONNECT_SWAPPED);
+
+ self->zoom_best_fit_action = g_action_map_lookup_action (G_ACTION_MAP (app), "zoom-best-fit");
+ g_signal_connect_object (self->zoom_best_fit_action,
+ "activate",
+ G_CALLBACK (photos_preview_view_zoom_best_fit),
+ self,
+ G_CONNECT_SWAPPED);
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (app), "zoom-in");
+ g_signal_connect_object (action, "activate", G_CALLBACK (photos_preview_view_zoom_in), self,
G_CONNECT_SWAPPED);
+
+ self->zoom_out_action = g_action_map_lookup_action (G_ACTION_MAP (app), "zoom-out");
+ g_signal_connect_object (self->zoom_out_action,
+ "activate",
+ G_CALLBACK (photos_preview_view_zoom_out),
+ self,
+ G_CONNECT_SWAPPED);
}
@@ -850,6 +1040,7 @@ photos_preview_view_set_node (PhotosPreviewView *self, GeglNode *node)
return;
view_container = gtk_stack_get_visible_child (GTK_STACK (self->stack));
+ self->zoom_best_fit = 0.0;
g_clear_object (&self->node);
if (node == NULL)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]