[gnome-photos/wip/rishi/gesture-zoom: 7/10] Encode the origin of the zoom event in the zoom-in/out GActions



commit a0e5e9ffdbc6035e85bc75b1c45299ecf1fd4f6c
Author: Debarshi Ray <debarshir gnome org>
Date:   Thu Oct 12 00:25:20 2017 +0200

    Encode the origin of the zoom event in the zoom-in/out GActions
    
    A subsequent commit will add support for zooming with touch gestures.
    This added flexibility readies the GActions for that.
    
    The current zooming interface provided by the zoom-in/out GActions is
    based on the notion of incremental steps. Each step represents one
    press/release of an accelerator key or mouse button, or one notch on
    the mouse's scroll wheel. The new zoom value is calculated for each
    step.
    
    However, touch gestures are different. The content needs to stick to
    the touch points while the gesture is active. This means that the ratio
    of the new and initial zoom values should be equal to the ratio of the
    distance between the current position of the touch points and the
    distance when the gesture was initiated. This is unlike the notion of
    discrete steps where the content would jump to the next zoom level.
    
    Commit 9590011fedb8e088 had hacked in the ability to encode the origin
    of the zoom event by using positive and negative arguments. This has
    been made more explicit by having a separate enumerated value for it.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=783922

 src/Makefile.am             |    2 +
 src/photos-application.c    |   19 ++++++--
 src/photos-enums.c.template |    1 +
 src/photos-preview-view.c   |   70 ++++++++++++++++++++--------
 src/photos-utils.c          |  107 +++++++++++++++++++++++++++++++++++++++++++
 src/photos-utils.h          |   18 +++++++
 src/photos-zoom-controls.c  |    8 +++-
 src/photos-zoom-controls.ui |    4 +-
 8 files changed, 203 insertions(+), 26 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 8bb7897..f8ff96a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -506,6 +506,7 @@ stamp-photos-enums.h: photos-enums.h.template
                        --template $(srcdir)/photos-enums.h.template \
                         $(srcdir)/photos-item-manager.h \
                         $(srcdir)/photos-operation-insta-common.h \
+                        $(srcdir)/photos-utils.h \
                 ) >> xgen-etbh \
                && ( cmp -s xgen-etbh photos-enums.h || cp xgen-etbh photos-enums.h ) \
                && rm -f xgen-etbh \
@@ -518,6 +519,7 @@ photos-enums.c: photos-enums.c.template
                        --template $(srcdir)/photos-enums.c.template \
                         $(srcdir)/photos-item-manager.h \
                         $(srcdir)/photos-operation-insta-common.h \
+                        $(srcdir)/photos-utils.h \
                 ) >> xgen-etbc \
                && ( cmp -s xgen-etbc photos-enums.c || cp xgen-etbc photos-enums.c ) \
                && rm -f xgen-etbc \
diff --git a/src/photos-application.c b/src/photos-application.c
index 3a4b02c..4957d98 100644
--- a/src/photos-application.c
+++ b/src/photos-application.c
@@ -1853,6 +1853,7 @@ photos_application_startup (GApplication *application)
   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};
+  gchar *detailed_action_name = NULL;
 
   photos_debug (PHOTOS_DEBUG_APPLICATION, "PhotosApplication::startup");
 
@@ -2062,10 +2063,10 @@ photos_application_startup (GApplication *application)
   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", G_VARIANT_TYPE_DOUBLE);
+  self->zoom_in_action = g_simple_action_new ("zoom-in", G_VARIANT_TYPE_VARDICT);
   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", G_VARIANT_TYPE_DOUBLE);
+  self->zoom_out_action = g_simple_action_new ("zoom-out", G_VARIANT_TYPE_VARDICT);
   g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (self->zoom_out_action));
 
   g_signal_connect_swapped (self->state->mode_cntrlr,
@@ -2089,8 +2090,18 @@ photos_application_startup (GApplication *application)
   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(-1.0)", zoom_in_accels);
-  gtk_application_set_accels_for_action (GTK_APPLICATION (self), "app.zoom-out(-1.0)", zoom_out_accels);
+
+  detailed_action_name = photos_utils_print_zoom_action_detailed_name ("app.zoom-in",
+                                                                       1.0,
+                                                                       
PHOTOS_ZOOM_EVENT_KEYBOARD_ACCELERATOR);
+  gtk_application_set_accels_for_action (GTK_APPLICATION (self), detailed_action_name, zoom_in_accels);
+  g_free (detailed_action_name);
+
+  detailed_action_name = photos_utils_print_zoom_action_detailed_name ("app.zoom-out",
+                                                                       1.0,
+                                                                       
PHOTOS_ZOOM_EVENT_KEYBOARD_ACCELERATOR);
+  gtk_application_set_accels_for_action (GTK_APPLICATION (self), detailed_action_name, zoom_out_accels);
+  g_free (detailed_action_name);
 
   g_signal_connect_swapped (self->state->item_mngr,
                             "items-changed",
diff --git a/src/photos-enums.c.template b/src/photos-enums.c.template
index 3b07c67..e93d20d 100644
--- a/src/photos-enums.c.template
+++ b/src/photos-enums.c.template
@@ -5,6 +5,7 @@
 #include "photos-enums.h"
 #include "photos-item-manager.h"
 #include "photos-operation-insta-common.h"
+#include "photos-utils.h"
 
 /*** END file-header ***/
 
diff --git a/src/photos-preview-view.c b/src/photos-preview-view.c
index 7a8619c..449bdf8 100644
--- a/src/photos-preview-view.c
+++ b/src/photos-preview-view.c
@@ -410,7 +410,7 @@ photos_preview_view_scroll_event (GtkWidget *widget, GdkEvent *event, gpointer u
     goto out;
 
   delta_abs = fabs (event->scroll.delta_y);
-  parameter = g_variant_new_double (delta_abs);
+  parameter = photos_utils_create_zoom_target_value (delta_abs, PHOTOS_ZOOM_EVENT_SCROLL);
   parameter = g_variant_ref_sink (parameter);
 
   if (event->scroll.delta_y < 0.0)
@@ -856,30 +856,46 @@ photos_preview_view_zoom_in (PhotosPreviewView *self, GVariant *parameter)
 {
   GtkWidget *view;
   GtkWidget *view_container;
+  PhotosZoomEvent event;
   gboolean best_fit;
   gdouble delta;
-  gdouble delta_abs;
   gdouble zoom;
   gdouble zoom_factor;
   gdouble zoom_factor_for_delta;
 
   g_return_if_fail (self->zoom_best_fit > 0.0);
 
-  delta = g_variant_get_double (parameter);
-  g_return_if_fail (photos_utils_equal_double (delta, -1.0) || delta >= 0.0);
+  event = photos_utils_get_zoom_event (parameter);
+  g_return_if_fail (event != PHOTOS_ZOOM_EVENT_NONE);
+
+  delta = photos_utils_get_zoom_delta (parameter);
+  g_return_if_fail ((event == PHOTOS_ZOOM_EVENT_KEYBOARD_ACCELERATOR && photos_utils_equal_double (delta, 
1.0))
+                    || (event == PHOTOS_ZOOM_EVENT_MOUSE_CLICK && photos_utils_equal_double (delta, 1.0))
+                    || (event == PHOTOS_ZOOM_EVENT_SCROLL && delta >= 0.0));
 
   view_container = gtk_stack_get_visible_child (GTK_STACK (self->stack));
   view = photos_preview_view_get_view_from_view_container (view_container);
 
   best_fit = photos_image_view_get_best_fit (PHOTOS_IMAGE_VIEW (view));
 
-  if (delta >= 0.0)
-    zoom_factor = best_fit ? ZOOM_FACTOR_2 : ZOOM_FACTOR_3;
-  else
-    zoom_factor = best_fit ? ZOOM_FACTOR_1 : ZOOM_FACTOR_2;
+  switch (event)
+    {
+    case PHOTOS_ZOOM_EVENT_KEYBOARD_ACCELERATOR:
+    case PHOTOS_ZOOM_EVENT_MOUSE_CLICK:
+      zoom_factor = best_fit ? ZOOM_FACTOR_1 : ZOOM_FACTOR_2;
+      break;
+
+    case PHOTOS_ZOOM_EVENT_SCROLL:
+      zoom_factor = best_fit ? ZOOM_FACTOR_2 : ZOOM_FACTOR_3;
+      break;
+
+    case PHOTOS_ZOOM_EVENT_NONE:
+    default:
+      g_assert_not_reached ();
+      break;
+    }
 
-  delta_abs = fabs (delta);
-  zoom_factor_for_delta = pow (zoom_factor, delta_abs);
+  zoom_factor_for_delta = pow (zoom_factor, delta);
 
   zoom = photos_image_view_get_zoom (PHOTOS_IMAGE_VIEW (view));
   zoom *= zoom_factor_for_delta;
@@ -898,27 +914,43 @@ photos_preview_view_zoom_out (PhotosPreviewView *self, GVariant *parameter)
 {
   GtkWidget *view;
   GtkWidget *view_container;
+  PhotosZoomEvent event;
   gdouble delta;
-  gdouble delta_abs;
   gdouble zoom;
   gdouble zoom_factor;
   gdouble zoom_factor_for_delta;
 
   g_return_if_fail (self->zoom_best_fit > 0.0);
 
-  delta = g_variant_get_double (parameter);
-  g_return_if_fail (photos_utils_equal_double (delta, -1.0) || delta >= 0.0);
+  event = photos_utils_get_zoom_event (parameter);
+  g_return_if_fail (event != PHOTOS_ZOOM_EVENT_NONE);
+
+  delta = photos_utils_get_zoom_delta (parameter);
+  g_return_if_fail ((event == PHOTOS_ZOOM_EVENT_KEYBOARD_ACCELERATOR && photos_utils_equal_double (delta, 
1.0))
+                    || (event == PHOTOS_ZOOM_EVENT_MOUSE_CLICK && photos_utils_equal_double (delta, 1.0))
+                    || (event == PHOTOS_ZOOM_EVENT_SCROLL && delta >= 0.0));
 
   view_container = gtk_stack_get_visible_child (GTK_STACK (self->stack));
   view = photos_preview_view_get_view_from_view_container (view_container);
 
-  if (delta >= 0.0)
-    zoom_factor = ZOOM_FACTOR_3;
-  else
-    zoom_factor = ZOOM_FACTOR_2;
+  switch (event)
+    {
+    case PHOTOS_ZOOM_EVENT_KEYBOARD_ACCELERATOR:
+    case PHOTOS_ZOOM_EVENT_MOUSE_CLICK:
+      zoom_factor = ZOOM_FACTOR_2;
+      break;
+
+    case PHOTOS_ZOOM_EVENT_SCROLL:
+      zoom_factor = ZOOM_FACTOR_3;
+      break;
+
+    case PHOTOS_ZOOM_EVENT_NONE:
+    default:
+      g_assert_not_reached ();
+      break;
+    }
 
-  delta_abs = fabs (delta);
-  zoom_factor_for_delta = pow (zoom_factor, delta_abs);
+  zoom_factor_for_delta = pow (zoom_factor, delta);
 
   zoom = photos_image_view_get_zoom (PHOTOS_IMAGE_VIEW (view));
   zoom /= zoom_factor_for_delta;
diff --git a/src/photos-utils.c b/src/photos-utils.c
index d48bb18..71a8d56 100644
--- a/src/photos-utils.c
+++ b/src/photos-utils.c
@@ -35,6 +35,7 @@
 #include <libgd/gd.h>
 
 #include "photos-application.h"
+#include "photos-enums.h"
 #include "photos-error.h"
 #include "photos-facebook-item.h"
 #include "photos-flickr-item.h"
@@ -394,6 +395,41 @@ photos_utils_create_thumbnail (GFile *file,
 }
 
 
+GVariant *
+photos_utils_create_zoom_target_value (gdouble delta, PhotosZoomEvent event)
+{
+  GEnumClass *zoom_event_class = NULL;
+  GEnumValue *event_value;
+  GVariant *delta_value;
+  GVariant *event_nick_value;
+  GVariant *ret_val = NULL;
+  GVariantBuilder builder;
+  const gchar *event_nick = "none";
+
+  g_return_val_if_fail (delta >= 0.0, NULL);
+  g_return_val_if_fail (event != PHOTOS_ZOOM_EVENT_NONE, NULL);
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+
+  delta_value = g_variant_new_double (delta);
+  g_variant_builder_add (&builder, "{sv}", "delta", delta_value);
+
+  zoom_event_class = G_ENUM_CLASS (g_type_class_ref (PHOTOS_TYPE_ZOOM_EVENT));
+
+  event_value = g_enum_get_value (zoom_event_class, (gint) event);
+  if (event_value != NULL)
+    event_nick = event_value->value_nick;
+
+  event_nick_value = g_variant_new_string (event_nick);
+  g_variant_builder_add (&builder, "{sv}", "event", event_nick_value);
+
+  ret_val = g_variant_builder_end (&builder);
+
+  g_type_class_unref (zoom_event_class);
+  return ret_val;
+}
+
+
 static GIcon *
 photos_utils_get_thumbnail_icon (const gchar *uri)
 {
@@ -482,6 +518,57 @@ photos_utils_get_icon_from_cursor (TrackerSparqlCursor *cursor)
 }
 
 
+gdouble
+photos_utils_get_zoom_delta (GVariant *dictionary)
+{
+  gdouble delta;
+  gdouble ret_val = -1.0;
+
+  g_return_val_if_fail (dictionary != NULL, -1.0);
+  g_return_val_if_fail (g_variant_is_of_type (dictionary, G_VARIANT_TYPE_VARDICT), -1.0);
+
+  if (!g_variant_lookup (dictionary, "delta", "d", &delta))
+    goto out;
+
+  ret_val = delta;
+
+ out:
+  g_return_val_if_fail (ret_val >= 0.0, -1.0);
+  return ret_val;
+}
+
+
+PhotosZoomEvent
+photos_utils_get_zoom_event (GVariant *dictionary)
+{
+  GEnumClass *zoom_event_class = NULL;
+  GEnumValue *event_value;
+  PhotosZoomEvent ret_val = PHOTOS_ZOOM_EVENT_NONE;
+  const gchar *event_str;
+
+  g_return_val_if_fail (dictionary != NULL, PHOTOS_ZOOM_EVENT_NONE);
+  g_return_val_if_fail (g_variant_is_of_type (dictionary, G_VARIANT_TYPE_VARDICT), PHOTOS_ZOOM_EVENT_NONE);
+
+  if (!g_variant_lookup (dictionary, "event", "&s", &event_str))
+    goto out;
+
+  zoom_event_class = G_ENUM_CLASS (g_type_class_ref (PHOTOS_TYPE_ZOOM_EVENT));
+
+  event_value = g_enum_get_value_by_nick (zoom_event_class, event_str);
+  if (event_value == NULL)
+    event_value = g_enum_get_value_by_name (zoom_event_class, event_str);
+  if (event_value == NULL)
+    goto out;
+
+  ret_val = (PhotosZoomEvent) event_value->value;
+
+ out:
+  g_clear_pointer (&zoom_event_class, g_type_class_unref);
+  g_return_val_if_fail (ret_val != PHOTOS_ZOOM_EVENT_NONE, PHOTOS_ZOOM_EVENT_NONE);
+  return ret_val;
+}
+
+
 GdkPixbuf *
 photos_utils_downscale_pixbuf_for_scale (GdkPixbuf *pixbuf, gint size, gint scale)
 {
@@ -1225,6 +1312,26 @@ photos_utils_object_list_free_full (GList *objects)
 }
 
 
+gchar *
+photos_utils_print_zoom_action_detailed_name (const gchar *action_name, gdouble delta, PhotosZoomEvent event)
+{
+  GVariant *target_value;
+  gchar *ret_val = NULL;
+
+  g_return_val_if_fail (action_name != NULL && action_name[0] != '\0', NULL);
+  g_return_val_if_fail (delta >= 0.0, NULL);
+  g_return_val_if_fail (event != PHOTOS_ZOOM_EVENT_NONE, NULL);
+
+  target_value = photos_utils_create_zoom_target_value (delta, event);
+  target_value = g_variant_ref_sink (target_value);
+
+  ret_val = g_action_print_detailed_name (action_name, target_value);
+
+  g_variant_unref (target_value);
+  return ret_val;
+}
+
+
 static gboolean
 photos_utils_adjustment_can_scroll (GtkAdjustment *adjustment)
 {
diff --git a/src/photos-utils.h b/src/photos-utils.h
index 9bb9de1..e40ef2a 100644
--- a/src/photos-utils.h
+++ b/src/photos-utils.h
@@ -52,6 +52,14 @@ G_BEGIN_DECLS
   "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#image-category-screenshot";
 #define PHOTOS_EXPORT_SUBPATH "Exports"
 
+typedef enum
+{
+  PHOTOS_ZOOM_EVENT_NONE,
+  PHOTOS_ZOOM_EVENT_KEYBOARD_ACCELERATOR,
+  PHOTOS_ZOOM_EVENT_MOUSE_CLICK,
+  PHOTOS_ZOOM_EVENT_SCROLL
+} PhotosZoomEvent;
+
 GdkPixbuf       *photos_utils_center_pixbuf               (GdkPixbuf *pixbuf, gint size);
 
 gchar           *photos_utils_convert_path_to_uri         (const gchar *path);
@@ -72,8 +80,14 @@ gboolean         photos_utils_create_thumbnail            (GFile *file,
                                                            GCancellable *cancellable,
                                                            GError **error);
 
+GVariant        *photos_utils_create_zoom_target_value    (gdouble delta, PhotosZoomEvent event);
+
 GIcon           *photos_utils_get_icon_from_cursor        (TrackerSparqlCursor *cursor);
 
+gdouble          photos_utils_get_zoom_delta              (GVariant *dictionary);
+
+PhotosZoomEvent  photos_utils_get_zoom_event              (GVariant *dictionary);
+
 GdkPixbuf       *photos_utils_downscale_pixbuf_for_scale  (GdkPixbuf *pixbuf, gint size, gint scale);
 
 void             photos_utils_draw_rectangle_handles      (cairo_t *cr,
@@ -159,6 +173,10 @@ void             photos_utils_list_box_header_func        (GtkListBoxRow *row,
 
 void             photos_utils_object_list_free_full       (GList *objects);
 
+gchar           *photos_utils_print_zoom_action_detailed_name (const gchar *action_name,
+                                                               gdouble delta,
+                                                               PhotosZoomEvent event);
+
 gboolean         photos_utils_scrolled_window_can_scroll  (GtkScrolledWindow *scrolled_window);
 
 void             photos_utils_scrolled_window_scroll      (GtkScrolledWindow *scrolled_window,
diff --git a/src/photos-zoom-controls.c b/src/photos-zoom-controls.c
index 388cf2c..726e722 100644
--- a/src/photos-zoom-controls.c
+++ b/src/photos-zoom-controls.c
@@ -25,6 +25,7 @@
 
 #include <gio/gio.h>
 
+#include "photos-utils.h"
 #include "photos-zoom-controls.h"
 
 
@@ -74,7 +75,12 @@ photos_zoom_controls_update_buttons (PhotosZoomControls *self)
     }
   else
     {
-      gtk_actionable_set_action_target (GTK_ACTIONABLE (self->zoom_toggle_button), "d", -1.0);
+      GVariant *target_value = NULL;
+
+      target_value = photos_utils_create_zoom_target_value (1.0, PHOTOS_ZOOM_EVENT_MOUSE_CLICK);
+      g_assert_true (g_variant_is_floating (target_value));
+
+      gtk_actionable_set_action_target_value (GTK_ACTIONABLE (self->zoom_toggle_button), target_value);
       gtk_actionable_set_action_name (GTK_ACTIONABLE (self->zoom_toggle_button), "app.zoom-in");
     }
 
diff --git a/src/photos-zoom-controls.ui b/src/photos-zoom-controls.ui
index 65e1d13..b5d2e66 100644
--- a/src/photos-zoom-controls.ui
+++ b/src/photos-zoom-controls.ui
@@ -39,7 +39,7 @@
                 <child>
                   <object class="GtkButton" id="zoom_in_button">
                     <property name="action_name">app.zoom-in</property>
-                    <property name="action_target">-1.0</property>
+                    <property name="action_target">{ 'delta': &lt;1.0&gt;, 'event': &lt;'mouse-click'&gt; 
}</property>
                     <style>
                       <class name="image-button"/>
                       <class name="osd"/>
@@ -54,7 +54,7 @@
                 <child>
                   <object class="GtkButton" id="zoom_out_button">
                     <property name="action_name">app.zoom-out</property>
-                    <property name="action_target">-1.0</property>
+                    <property name="action_target">{ 'delta': &lt;1.0&gt;, 'event': &lt;'mouse-click'&gt; 
}</property>
                     <style>
                       <class name="image-button"/>
                       <class name="osd"/>


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