[eog] EogZoomEntry: Replace zoom GtkRange



commit b5d37f3916f7611082d1b20598f2e703d4f0fecb
Author: Felix Riemann <friemann gnome org>
Date:   Sun Feb 12 20:39:20 2017 +0100

    EogZoomEntry: Replace zoom GtkRange
    
    This replaces the zoom GtkRange with a combined GtkEntry with buttons
    and menu. This allows more control than the GtkRange-based solution
    which wasn't even able to use the full zoom range.
    EogZoomEntry is based on Evince's EvZoomAction.

 data/popup-menus.ui   |   11 +
 src/Makefile.am       |   16 +-
 src/eog-scroll-view.c |  674 ++++++++++++++++++++++++------------------------
 src/eog-scroll-view.h |    3 +
 src/eog-window.c      |  115 +--------
 src/eog-zoom-entry.c  |  335 ++++++++++++++++++++++++
 src/eog-zoom-entry.h  |   41 +++
 src/eog.gresource.xml |    1 +
 8 files changed, 746 insertions(+), 450 deletions(-)
---
diff --git a/data/popup-menus.ui b/data/popup-menus.ui
index 846ec17..aae780c 100644
--- a/data/popup-menus.ui
+++ b/data/popup-menus.ui
@@ -51,4 +51,15 @@
       </item>
     </section>
   </menu>
+  <menu id="zoom-menu">
+      <section>
+        <item>
+          <attribute name="label" translatable="yes">_Best fit</attribute>
+          <attribute name="action">win.toggle-zoom-fit</attribute>
+        </item>
+      </section>
+      <section>
+      </section>
+    </menu>
+
 </interface>
diff --git a/src/Makefile.am b/src/Makefile.am
index 1d1ae98..735dbd4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,14 +25,15 @@ NOINST_H_FILES =                    \
        eog-metadata-reader-jpg.h       \
        eog-metadata-reader-png.h       \
        eog-pixbuf-util.h               \
-       eog-plugin-engine.h             \
+       eog-plugin-engine.h             \
        eog-preferences-dialog.h        \
        eog-print.h                     \
-       eog-print-image-setup.h         \
-       eog-print-preview.h             \
+       eog-print-image-setup.h         \
+       eog-print-preview.h             \
        eog-save-as-dialog-helper.h     \
        eog-session.h                   \
        eog-util.h                      \
+       eog-zoom-entry.h                \
        zoom.h
 
 INST_H_FILES =                         \
@@ -63,7 +64,7 @@ libeog_c_files =                      \
        eog-application.c               \
        eog-application-activatable.c   \
        eog-clipboard-handler.c         \
-       eog-close-confirmation-dialog.c \
+       eog-close-confirmation-dialog.c \
        eog-debug.c                     \
        eog-error-message-area.c        \
        eog-file-chooser.c              \
@@ -78,11 +79,11 @@ libeog_c_files =                    \
        eog-metadata-reader-jpg.c       \
        eog-metadata-reader-png.c       \
        eog-pixbuf-util.c               \
-       eog-plugin-engine.c             \
+       eog-plugin-engine.c             \
        eog-preferences-dialog.c        \
        eog-print.c                     \
-       eog-print-image-setup.c         \
-       eog-print-preview.c             \
+       eog-print-image-setup.c         \
+       eog-print-preview.c             \
        eog-properties-dialog.c         \
        eog-save-as-dialog-helper.c     \
        eog-scroll-view.c               \
@@ -97,6 +98,7 @@ libeog_c_files =                      \
        eog-util.c                      \
        eog-window-activatable.c        \
        eog-window.c                    \
+       eog-zoom-entry.c                \
        zoom.c
 
 libeog_la_SOURCES =                    \
diff --git a/src/eog-scroll-view.c b/src/eog-scroll-view.c
index 53fea06..8c1bf00 100644
--- a/src/eog-scroll-view.c
+++ b/src/eog-scroll-view.c
@@ -19,8 +19,8 @@
 #include "zoom.h"
 
 /* Maximum zoom factor */
-#define MAX_ZOOM_FACTOR 20
-#define MIN_ZOOM_FACTOR 0.02
+#define MAX_ZOOM_FACTOR EOG_SCROLL_VIEW_MAX_ZOOM_FACTOR
+#define MIN_ZOOM_FACTOR EOG_SCROLL_VIEW_MIN_ZOOM_FACTOR
 
 /* Default increment for zooming.  The current zoom factor is multiplied or
  * divided by this amount on every zooming step.  For consistency, you should
@@ -77,7 +77,7 @@ typedef enum {
 
 /* Drag 'n Drop */
 static GtkTargetEntry target_table[] = {
-       { "text/uri-list", 0, 0},
+        { "text/uri-list", 0, 0},
 };
 
 enum {
@@ -182,11 +182,11 @@ static void set_zoom_fit (EogScrollView *view);
 /* static void request_paint_area (EogScrollView *view, GdkRectangle *area); */
 static void set_minimum_zoom_factor (EogScrollView *view);
 static void view_on_drag_begin_cb (GtkWidget *widget, GdkDragContext *context,
-                                  gpointer user_data);
+                                   gpointer user_data);
 static void view_on_drag_data_get_cb (GtkWidget *widget,
-                                     GdkDragContext*drag_context,
-                                     GtkSelectionData *data, guint info,
-                                     guint time, gpointer user_data);
+                                      GdkDragContext*drag_context,
+                                      GtkSelectionData *data, guint info,
+                                      guint time, gpointer user_data);
 static void _set_zoom_mode_internal (EogScrollView *view, EogZoomMode mode);
 static gboolean eog_scroll_view_get_image_coords (EogScrollView *view, gint *x,
                                                   gint *y, gint *width,
@@ -198,7 +198,7 @@ G_DEFINE_TYPE_WITH_PRIVATE (EogScrollView, eog_scroll_view, GTK_TYPE_GRID)
 
 /*===================================
     widget size changing handler &
-        util functions
+       util functions
   ---------------------------------*/
 
 static cairo_surface_t *
@@ -208,9 +208,9 @@ create_surface_from_pixbuf (EogScrollView *view, GdkPixbuf *pixbuf)
        cairo_t *cr;
 
        surface = gdk_window_create_similar_surface (gtk_widget_get_window (view->priv->display),
-                                                    CAIRO_CONTENT_COLOR | CAIRO_CONTENT_ALPHA,
-                                                    gdk_pixbuf_get_width (pixbuf),
-                                                    gdk_pixbuf_get_height (pixbuf));
+                                                    CAIRO_CONTENT_COLOR | CAIRO_CONTENT_ALPHA,
+                                                    gdk_pixbuf_get_width (pixbuf),
+                                                    gdk_pixbuf_get_height (pixbuf));
        cr = cairo_create (surface);
        gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
        cairo_paint (cr);
@@ -273,10 +273,10 @@ compute_scaled_size (EogScrollView *view, double zoom, int *width, int *height)
  */
 static void
 compute_center_zoom_offsets (EogScrollView *view,
-                            double old_zoom, double new_zoom,
-                            int width, int height,
-                            double zoom_x_anchor, double zoom_y_anchor,
-                            int *xofs, int *yofs)
+                             double old_zoom, double new_zoom,
+                             int width, int height,
+                             double zoom_x_anchor, double zoom_y_anchor,
+                             int *xofs, int *yofs)
 {
        EogScrollViewPrivate *priv;
        int old_scaled_width, old_scaled_height;
@@ -286,7 +286,7 @@ compute_center_zoom_offsets (EogScrollView *view,
        priv = view->priv;
 
        compute_scaled_size (view, old_zoom,
-                            &old_scaled_width, &old_scaled_height);
+                            &old_scaled_width, &old_scaled_height);
 
        if (old_scaled_width < width)
                view_cx = (zoom_x_anchor * old_scaled_width) / old_zoom;
@@ -299,7 +299,7 @@ compute_center_zoom_offsets (EogScrollView *view,
                view_cy = (priv->yofs + zoom_y_anchor * height) / old_zoom;
 
        compute_scaled_size (view, new_zoom,
-                            &new_scaled_width, &new_scaled_height);
+                            &new_scaled_width, &new_scaled_height);
 
        if (new_scaled_width < width)
                *xofs = 0;
@@ -349,16 +349,16 @@ update_scrollbar_values (EogScrollView *view)
                priv->xofs = CLAMP (priv->xofs, 0, upper - page_size);
 
                g_signal_handlers_block_matched (
-                       priv->hadj, G_SIGNAL_MATCH_DATA,
-                       0, 0, NULL, NULL, view);
+                       priv->hadj, G_SIGNAL_MATCH_DATA,
+                       0, 0, NULL, NULL, view);
 
                gtk_adjustment_configure (priv->hadj, priv->xofs, lower,
-                                         upper, step_increment,
-                                         page_increment, page_size);
+                                         upper, step_increment,
+                                         page_increment, page_size);
 
                g_signal_handlers_unblock_matched (
-                       priv->hadj, G_SIGNAL_MATCH_DATA,
-                       0, 0, NULL, NULL, view);
+                       priv->hadj, G_SIGNAL_MATCH_DATA,
+                       0, 0, NULL, NULL, view);
        }
 
        if (gtk_widget_get_visible (GTK_WIDGET (priv->vbar))) {
@@ -371,16 +371,16 @@ update_scrollbar_values (EogScrollView *view)
                priv->yofs = CLAMP (priv->yofs, 0, upper - page_size);
 
                g_signal_handlers_block_matched (
-                       priv->vadj, G_SIGNAL_MATCH_DATA,
-                       0, 0, NULL, NULL, view);
+                       priv->vadj, G_SIGNAL_MATCH_DATA,
+                       0, 0, NULL, NULL, view);
 
                gtk_adjustment_configure (priv->vadj, priv->yofs, lower,
-                                         upper, step_increment,
-                                         page_increment, page_size);
+                                         upper, step_increment,
+                                         page_increment, page_size);
 
                g_signal_handlers_unblock_matched (
-                       priv->vadj, G_SIGNAL_MATCH_DATA,
-                       0, 0, NULL, NULL, view);
+                       priv->vadj, G_SIGNAL_MATCH_DATA,
+                       0, 0, NULL, NULL, view);
        }
 }
 
@@ -400,15 +400,15 @@ eog_scroll_view_set_cursor (EogScrollView *view, EogScrollViewCursor new_cursor)
        view->priv->cursor = new_cursor;
 
        switch (new_cursor) {
-               case EOG_SCROLL_VIEW_CURSOR_NORMAL:
-                       gdk_window_set_cursor (gtk_widget_get_window (widget), NULL);
-                       break;
-                case EOG_SCROLL_VIEW_CURSOR_HIDDEN:
-                       cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR);
-                        break;
-               case EOG_SCROLL_VIEW_CURSOR_DRAG:
-                       cursor = gdk_cursor_new_for_display (display, GDK_FLEUR);
-                       break;
+               case EOG_SCROLL_VIEW_CURSOR_NORMAL:
+                       gdk_window_set_cursor (gtk_widget_get_window (widget), NULL);
+                       break;
+               case EOG_SCROLL_VIEW_CURSOR_HIDDEN:
+                       cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR);
+                       break;
+               case EOG_SCROLL_VIEW_CURSOR_DRAG:
+                       cursor = gdk_cursor_new_for_display (display, GDK_FLEUR);
+                       break;
        }
 
        if (cursor) {
@@ -455,7 +455,7 @@ check_scrollbar_visibility (EogScrollView *view, GtkAllocation *alloc)
        bar_width = req.width;
 
        eog_debug_message (DEBUG_WINDOW, "Widget Size allocate: %i, %i   Bar: %i, %i\n",
-                          width, height, bar_width, bar_height);
+                          width, height, bar_width, bar_height);
 
        hbar_visible = vbar_visible = FALSE;
        if (priv->zoom_mode == EOG_ZOOM_MODE_SHRINK_TO_FIT)
@@ -471,7 +471,7 @@ check_scrollbar_visibility (EogScrollView *view, GtkAllocation *alloc)
                else
                        vbar_visible = TRUE;
        }
-        else if (img_height > height) {
+       else if (img_height > height) {
                vbar_visible = TRUE;
                if (img_width <= (width - bar_width))
                        hbar_visible = FALSE;
@@ -524,7 +524,7 @@ is_image_movable (EogScrollView *view)
 }
 
 /*===================================
-          drawing core
+         drawing core
   ---------------------------------*/
 
 static void
@@ -570,8 +570,8 @@ create_background_surface (EogScrollView *view)
 
        get_transparency_params (view, &check_size, &check_1, &check_2);
        surface = gdk_window_create_similar_surface (gtk_widget_get_window (view->priv->display),
-                                                    CAIRO_CONTENT_COLOR_ALPHA,
-                                                    check_size * 2, check_size * 2);
+                                                    CAIRO_CONTENT_COLOR_ALPHA,
+                                                    check_size * 2, check_size * 2);
        cairo_t* cr = cairo_create (surface);
 
        /* Use source operator to make fully transparent work */
@@ -617,14 +617,14 @@ scroll_to (EogScrollView *view, int x, int y, gboolean change_adjustments)
        /* Check bounds & Compute offsets */
        if (gtk_widget_get_visible (priv->hbar)) {
                x = CLAMP (x, 0, gtk_adjustment_get_upper (priv->hadj)
-                                - gtk_adjustment_get_page_size (priv->hadj));
+                                - gtk_adjustment_get_page_size (priv->hadj));
                xofs = x - priv->xofs;
        } else
                xofs = 0;
 
        if (gtk_widget_get_visible (priv->vbar)) {
                y = CLAMP (y, 0, gtk_adjustment_get_upper (priv->vadj)
-                                - gtk_adjustment_get_page_size (priv->vadj));
+                                - gtk_adjustment_get_page_size (priv->vadj));
                yofs = y - priv->yofs;
        } else
                yofs = 0;
@@ -659,21 +659,21 @@ scroll_to (EogScrollView *view, int x, int y, gboolean change_adjustments)
                return;
 
        g_signal_handlers_block_matched (
-               priv->hadj, G_SIGNAL_MATCH_DATA,
-               0, 0, NULL, NULL, view);
+               priv->hadj, G_SIGNAL_MATCH_DATA,
+               0, 0, NULL, NULL, view);
        g_signal_handlers_block_matched (
-               priv->vadj, G_SIGNAL_MATCH_DATA,
-               0, 0, NULL, NULL, view);
+               priv->vadj, G_SIGNAL_MATCH_DATA,
+               0, 0, NULL, NULL, view);
 
        gtk_adjustment_set_value (priv->hadj, x);
        gtk_adjustment_set_value (priv->vadj, y);
 
        g_signal_handlers_unblock_matched (
-               priv->hadj, G_SIGNAL_MATCH_DATA,
-               0, 0, NULL, NULL, view);
+               priv->hadj, G_SIGNAL_MATCH_DATA,
+               0, 0, NULL, NULL, view);
        g_signal_handlers_unblock_matched (
-               priv->vadj, G_SIGNAL_MATCH_DATA,
-               0, 0, NULL, NULL, view);
+               priv->vadj, G_SIGNAL_MATCH_DATA,
+               0, 0, NULL, NULL, view);
 }
 
 /* Scrolls the image view by the specified offsets.  Notifies the adjustments
@@ -701,7 +701,7 @@ adjustment_changed_cb (GtkAdjustment *adj, gpointer data)
        priv = view->priv;
 
        scroll_to (view, gtk_adjustment_get_value (priv->hadj),
-                  gtk_adjustment_get_value (priv->vadj), FALSE);
+                  gtk_adjustment_get_value (priv->vadj), FALSE);
 }
 
 
@@ -729,8 +729,8 @@ set_minimum_zoom_factor (EogScrollView *view)
        g_return_if_fail (EOG_IS_SCROLL_VIEW (view));
 
        view->priv->min_zoom = MAX (1.0 / gdk_pixbuf_get_width (view->priv->pixbuf),
-                                   MAX(1.0 / gdk_pixbuf_get_height (view->priv->pixbuf),
-                                       MIN_ZOOM_FACTOR) );
+                                   MAX(1.0 / gdk_pixbuf_get_height (view->priv->pixbuf),
+                                       MIN_ZOOM_FACTOR) );
        return;
 }
 
@@ -751,7 +751,7 @@ set_minimum_zoom_factor (EogScrollView *view)
  **/
 static void
 set_zoom (EogScrollView *view, double zoom,
-         gboolean have_anchor, int anchorx, int anchory)
+          gboolean have_anchor, int anchorx, int anchory)
 {
        EogScrollViewPrivate *priv;
        GtkAllocation allocation;
@@ -787,9 +787,9 @@ set_zoom (EogScrollView *view, double zoom,
        }
 
        compute_center_zoom_offsets (view, priv->zoom, zoom,
-                                    allocation.width, allocation.height,
-                                    x_rel, y_rel,
-                                    &xofs, &yofs);
+                                    allocation.width, allocation.height,
+                                    x_rel, y_rel,
+                                    &xofs, &yofs);
 
        /* set new values */
        priv->xofs = xofs; /* (img_width * x_rel * zoom) - anchorx; */
@@ -840,9 +840,9 @@ set_zoom_fit (EogScrollView *view)
        gtk_widget_get_allocation (GTK_WIDGET(priv->display), &allocation);
 
        new_zoom = zoom_fit_scale (allocation.width, allocation.height,
-                                  gdk_pixbuf_get_width (priv->pixbuf),
-                                  gdk_pixbuf_get_height (priv->pixbuf),
-                                  priv->upscale);
+                                  gdk_pixbuf_get_width (priv->pixbuf),
+                                  gdk_pixbuf_get_height (priv->pixbuf),
+                                  priv->upscale);
 
        if (new_zoom > MAX_ZOOM_FACTOR)
                new_zoom = MAX_ZOOM_FACTOR;
@@ -1014,9 +1014,9 @@ eog_scroll_view_button_press_event (GtkWidget *widget, GdkEventButton *event, gp
                return FALSE;
 
        switch (event->button) {
-               case 1:
-               case 2:
-                        if (event->button == 1 && !priv->scroll_wheel_zoom &&
+               case 1:
+               case 2:
+                       if (event->button == 1 && !priv->scroll_wheel_zoom &&
                            !(event->state & GDK_CONTROL_MASK))
                                break;
 
@@ -1032,8 +1032,8 @@ eog_scroll_view_button_press_event (GtkWidget *widget, GdkEventButton *event, gp
 
                                return TRUE;
                        }
-               default:
-                       break;
+               default:
+                       break;
        }
 
        return FALSE;
@@ -1053,16 +1053,16 @@ eog_scroll_view_button_release_event (GtkWidget *widget, GdkEventButton *event,
                return FALSE;
 
        switch (event->button) {
-               case 1:
-               case 2:
-                       drag_to (view, event->x, event->y);
+               case 1:
+               case 2:
+                       drag_to (view, event->x, event->y);
                        priv->dragging = FALSE;
 
                        eog_scroll_view_set_cursor (view, EOG_SCROLL_VIEW_CURSOR_NORMAL);
-                       break;
+                       break;
 
-               default:
-                       break;
+               default:
+                       break;
        }
 
        return TRUE;
@@ -1119,23 +1119,23 @@ eog_scroll_view_scroll_event (GtkWidget *widget, GdkEventScroll *event, gpointer
                return FALSE;
        }
 
-        if (priv->scroll_wheel_zoom) {
+       if (priv->scroll_wheel_zoom) {
                if (event->state & GDK_SHIFT_MASK)
                        scroll_by (view, yofs, xofs);
                else if (event->state & GDK_CONTROL_MASK)
                        scroll_by (view, xofs, yofs);
                else
                        set_zoom (view, priv->zoom * zoom_factor,
-                                 TRUE, event->x, event->y);
+                                 TRUE, event->x, event->y);
        } else {
                if (event->state & GDK_SHIFT_MASK)
                        scroll_by (view, yofs, xofs);
                else if (event->state & GDK_CONTROL_MASK)
                        set_zoom (view, priv->zoom * zoom_factor,
-                                 TRUE, event->x, event->y);
+                                 TRUE, event->x, event->y);
                else
                        scroll_by (view, xofs, yofs);
-        }
+       }
 
        return TRUE;
 }
@@ -1194,7 +1194,7 @@ eog_scroll_view_size_allocate (GtkWidget *widget, GtkAllocation *alloc)
        check_scrollbar_visibility (view, alloc);
 
        GTK_WIDGET_CLASS (eog_scroll_view_parent_class)->size_allocate (widget
-                                                                       ,alloc);
+                                                                       ,alloc);
 }
 
 static void
@@ -1237,8 +1237,8 @@ display_size_change (GtkWidget *widget, GdkEventConfigure *event, gpointer data)
 
 static gboolean
 eog_scroll_view_focus_in_event (GtkWidget     *widget,
-                           GdkEventFocus *event,
-                           gpointer data)
+                            GdkEventFocus *event,
+                            gpointer data)
 {
        g_signal_stop_emission_by_name (G_OBJECT (widget), "focus_in_event");
        return FALSE;
@@ -1246,8 +1246,8 @@ eog_scroll_view_focus_in_event (GtkWidget     *widget,
 
 static gboolean
 eog_scroll_view_focus_out_event (GtkWidget     *widget,
-                            GdkEventFocus *event,
-                            gpointer data)
+                             GdkEventFocus *event,
+                             gpointer data)
 {
        g_signal_stop_emission_by_name (G_OBJECT (widget), "focus_out_event");
        return FALSE;
@@ -1316,24 +1316,24 @@ display_draw (GtkWidget *widget, cairo_t *cr, gpointer data)
                                          &scaled_width, &scaled_height);
 
        eog_debug_message (DEBUG_WINDOW, "zoom %.2f, xofs: %i, yofs: %i scaled w: %i h: %i\n",
-                          priv->zoom, xofs, yofs, scaled_width, scaled_height);
+                          priv->zoom, xofs, yofs, scaled_width, scaled_height);
 
        /* Paint the background */
        gtk_widget_get_allocation (GTK_WIDGET (priv->display), &allocation);
        cairo_rectangle (cr, 0, 0, allocation.width, allocation.height);
        if (priv->transp_style != EOG_TRANSP_BACKGROUND)
                cairo_rectangle (cr, MAX (0, xofs), MAX (0, yofs),
-                                scaled_width, scaled_height);
+                                scaled_width, scaled_height);
        if (priv->override_bg_color != NULL)
                background_color = priv->override_bg_color;
        else if (priv->use_bg_color)
                background_color = priv->background_color;
        if (background_color != NULL)
                cairo_set_source_rgba (cr,
-                                      background_color->red,
-                                      background_color->green,
-                                      background_color->blue,
-                                      background_color->alpha);
+                                      background_color->red,
+                                      background_color->green,
+                                      background_color->blue,
+                                      background_color->alpha);
        else
                cairo_set_source (cr, gdk_window_get_background_pattern (gtk_widget_get_window 
(priv->display)));
        cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
@@ -1435,8 +1435,8 @@ display_draw (GtkWidget *widget, cairo_t *cr, gpointer data)
 
 static void
 zoom_gesture_begin_cb (GtkGestureZoom   *gesture,
-                      GdkEventSequence *sequence,
-                      EogScrollView    *view)
+                       GdkEventSequence *sequence,
+                       EogScrollView    *view)
 {
        gdouble center_x, center_y;
        EogScrollViewPrivate *priv;
@@ -1445,7 +1445,7 @@ zoom_gesture_begin_cb (GtkGestureZoom   *gesture,
 
        /* Displace dragging point to gesture center */
        gtk_gesture_get_bounding_box_center (GTK_GESTURE (gesture),
-                                             &center_x, &center_y);
+                                            &center_x, &center_y);
        priv->drag_anchor_x = center_x;
        priv->drag_anchor_y = center_y;
        priv->drag_ofs_x = priv->xofs;
@@ -1453,13 +1453,13 @@ zoom_gesture_begin_cb (GtkGestureZoom   *gesture,
        priv->dragging = TRUE;
        priv->initial_zoom = priv->zoom;
 
-        gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
+       gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
 }
 
 static void
 zoom_gesture_update_cb (GtkGestureZoom   *gesture,
-                       GdkEventSequence *sequence,
-                       EogScrollView    *view)
+                        GdkEventSequence *sequence,
+                        EogScrollView    *view)
 {
        gdouble center_x, center_y, scale;
        EogScrollViewPrivate *priv;
@@ -1467,29 +1467,29 @@ zoom_gesture_update_cb (GtkGestureZoom   *gesture,
        priv = view->priv;
        scale = gtk_gesture_zoom_get_scale_delta (gesture);
        gtk_gesture_get_bounding_box_center (GTK_GESTURE (gesture),
-                                             &center_x, &center_y);
+                                            &center_x, &center_y);
 
        drag_to (view, center_x, center_y);
        set_zoom (view, priv->initial_zoom * scale, TRUE,
-                 center_x, center_y);
+                 center_x, center_y);
 }
 
 static void
 zoom_gesture_end_cb (GtkGestureZoom   *gesture,
-                    GdkEventSequence *sequence,
-                    EogScrollView    *view)
+                     GdkEventSequence *sequence,
+                     EogScrollView    *view)
 {
        EogScrollViewPrivate *priv;
 
        priv = view->priv;
        priv->dragging = FALSE;
-        eog_scroll_view_set_cursor (view, EOG_SCROLL_VIEW_CURSOR_NORMAL);
+       eog_scroll_view_set_cursor (view, EOG_SCROLL_VIEW_CURSOR_NORMAL);
 }
 
 static void
 rotate_gesture_begin_cb (GtkGesture       *gesture,
-                        GdkEventSequence *sequence,
-                        EogScrollView    *view)
+                         GdkEventSequence *sequence,
+                         EogScrollView    *view)
 {
        EogScrollViewPrivate *priv;
 
@@ -1499,15 +1499,15 @@ rotate_gesture_begin_cb (GtkGesture       *gesture,
 
 static void
 pan_gesture_pan_cb (GtkGesturePan   *gesture,
-                   GtkPanDirection  direction,
-                   gdouble          offset,
-                   EogScrollView   *view)
+                    GtkPanDirection  direction,
+                    gdouble          offset,
+                    EogScrollView   *view)
 {
        EogScrollViewPrivate *priv;
 
        if (eog_scroll_view_scrollbars_visible (view)) {
                gtk_gesture_set_state (GTK_GESTURE (gesture),
-                                      GTK_EVENT_SEQUENCE_DENIED);
+                                      GTK_EVENT_SEQUENCE_DENIED);
                return;
        }
 
@@ -1529,8 +1529,8 @@ pan_gesture_pan_cb (GtkGesturePan   *gesture,
 
 static void
 pan_gesture_end_cb (GtkGesture       *gesture,
-                   GdkEventSequence *sequence,
-                   EogScrollView    *view)
+                    GdkEventSequence *sequence,
+                    EogScrollView    *view)
 {
        EogScrollViewPrivate *priv;
 
@@ -1549,22 +1549,22 @@ pan_gesture_end_cb (GtkGesture       *gesture,
 
 static gboolean
 scroll_view_check_angle (gdouble angle,
-                        gdouble min,
-                        gdouble max,
-                        gdouble threshold)
+                         gdouble min,
+                         gdouble max,
+                         gdouble threshold)
 {
        if (min < max) {
                return (angle > min - threshold &&
-                       angle < max + threshold);
+                       angle < max + threshold);
        } else {
                return (angle < max + threshold ||
-                       angle > min - threshold);
+                       angle > min - threshold);
        }
 }
 
 static EogRotationState
 scroll_view_get_rotate_state (EogScrollView *view,
-                             gdouble        delta)
+                              gdouble        delta)
 {
        EogScrollViewPrivate *priv;
 
@@ -1574,22 +1574,22 @@ scroll_view_get_rotate_state (EogScrollView *view,
        switch (priv->rotate_state) {
        case EOG_ROTATION_0:
                if (scroll_view_check_angle (delta, G_PI * 7 / 4,
-                                            G_PI / 4, THRESHOLD))
+                                            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))
+                                            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))
+                                            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))
+                                            G_PI * 7 / 4, THRESHOLD))
                        return priv->rotate_state;
                break;
        default:
@@ -1610,17 +1610,17 @@ scroll_view_get_rotate_state (EogScrollView *view,
 
 static void
 rotate_gesture_angle_changed_cb (GtkGestureRotate *rotate,
-                                gdouble           angle,
-                                gdouble           delta,
-                                EogScrollView    *view)
+                                 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 }
+               { 0,   90,  180, 270 },
+               { 270, 0,   90,  180 },
+               { 180, 270, 0,   90 },
+               { 90,  180, 270, 0 }
        };
        gint rotate_angle;
 
@@ -1669,11 +1669,11 @@ image_changed_cb (EogImage *img, gpointer data)
        update_pixbuf (EOG_SCROLL_VIEW (data), eog_image_get_pixbuf (img));
 
        _set_zoom_mode_internal (EOG_SCROLL_VIEW (data),
-                                EOG_ZOOM_MODE_SHRINK_TO_FIT);
+                                EOG_ZOOM_MODE_SHRINK_TO_FIT);
 }
 
 /*===================================
-         public API
+        public API
   ---------------------------------*/
 
 void
@@ -1782,12 +1782,12 @@ eog_scroll_view_set_transparency_color (EogScrollView *view, GdkRGBA *color)
 
 void
 eog_scroll_view_set_transparency (EogScrollView        *view,
-                                 EogTransparencyStyle  style)
+                                  EogTransparencyStyle  style)
 {
        EogScrollViewPrivate *priv;
 
        g_return_if_fail (EOG_IS_SCROLL_VIEW (view));
-       
+
        priv = view->priv;
 
        if (priv->transp_style != style) {
@@ -1800,9 +1800,9 @@ eog_scroll_view_set_transparency (EogScrollView        *view,
 /* zoom api */
 
 static double preferred_zoom_levels[] = {
-       1.0 / 100, 1.0 / 50, 1.0 / 20,
-       1.0 / 10.0, 1.0 / 5.0, 1.0 / 3.0, 1.0 / 2.0, 1.0 / 1.5,
-       1.0, 1 / 0.75, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0,
+        1.0 / 100, 1.0 / 50, 1.0 / 20,
+        1.0 / 10.0, 1.0 / 5.0, 1.0 / 3.0, 1.0 / 2.0, 1.0 / 1.5,
+        1.0, 1 / 0.75, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0,
         11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0
 };
 static const gint n_zoom_levels = (sizeof (preferred_zoom_levels) / sizeof (double));
@@ -1826,7 +1826,7 @@ eog_scroll_view_zoom_in (EogScrollView *view, gboolean smooth)
 
                for (i = 0; i < n_zoom_levels; i++) {
                        if (preferred_zoom_levels [i] - priv->zoom
-                                       > DOUBLE_EQUAL_MAX_DIFF) {
+                                       > DOUBLE_EQUAL_MAX_DIFF) {
                                index = i;
                                break;
                        }
@@ -1862,7 +1862,7 @@ eog_scroll_view_zoom_out (EogScrollView *view, gboolean smooth)
 
                for (i = n_zoom_levels - 1; i >= 0; i--) {
                        if (priv->zoom - preferred_zoom_levels [i]
-                                       > DOUBLE_EQUAL_MAX_DIFF) {
+                                       > DOUBLE_EQUAL_MAX_DIFF) {
                                index = i;
                                break;
                        }
@@ -1925,7 +1925,7 @@ eog_scroll_view_get_zoom_is_max (EogScrollView *view)
 static void
 display_next_frame_cb (EogImage *image, gint delay, gpointer data)
 {
-       EogScrollViewPrivate *priv;
+       EogScrollViewPrivate *priv;
        EogScrollView *view;
 
        if (!EOG_IS_SCROLL_VIEW (data))
@@ -1936,7 +1936,7 @@ display_next_frame_cb (EogImage *image, gint delay, gpointer data)
 
        update_pixbuf (view, eog_image_get_pixbuf (image));
 
-       gtk_widget_queue_draw (GTK_WIDGET (priv->display)); 
+       gtk_widget_queue_draw (GTK_WIDGET (priv->display));
 }
 
 void
@@ -1966,12 +1966,12 @@ eog_scroll_view_set_image (EogScrollView *view, EogImage *image)
                        update_pixbuf (view, eog_image_get_pixbuf (image));
                        /* priv->progressive_state = PROGRESSIVE_NONE; */
                        _set_zoom_mode_internal (view,
-                                                EOG_ZOOM_MODE_SHRINK_TO_FIT);
+                                                EOG_ZOOM_MODE_SHRINK_TO_FIT);
 
                }
 #if 0
                else if ((is_zoomed_in (view) && priv->interp_type_in != CAIRO_FILTER_NEAREST) ||
-                        (is_zoomed_out (view) && priv->interp_type_out != CAIRO_FILTER_NEAREST))
+                        (is_zoomed_out (view) && priv->interp_type_out != CAIRO_FILTER_NEAREST))
                {
                        /* paint antialiased image version */
                        priv->progressive_state = PROGRESSIVE_POLISHING;
@@ -1980,11 +1980,11 @@ eog_scroll_view_set_image (EogScrollView *view, EogImage *image)
 #endif
 
                priv->image_changed_id = g_signal_connect (image, "changed",
-                                                          (GCallback) image_changed_cb, view);
+                                                          (GCallback) image_changed_cb, view);
                if (eog_image_is_animation (image) == TRUE ) {
                        eog_image_start_animation (image);
-                       priv->frame_changed_id = g_signal_connect (image, "next-frame", 
-                                                                   (GCallback) display_next_frame_cb, view);
+                       priv->frame_changed_id = g_signal_connect (image, "next-frame",
+                                                                   (GCallback) display_next_frame_cb, view);
                }
        } else {
                gtk_widget_queue_draw (GTK_WIDGET (priv->display));
@@ -2034,8 +2034,8 @@ eog_scroll_view_scrollbars_visible (EogScrollView *view)
 
 static gboolean
 sv_string_to_rgba_mapping (GValue   *value,
-                           GVariant *variant,
-                           gpointer  user_data)
+                            GVariant *variant,
+                            gpointer  user_data)
 {
        GdkRGBA color;
 
@@ -2051,8 +2051,8 @@ sv_string_to_rgba_mapping (GValue   *value,
 
 static GVariant*
 sv_rgba_to_string_mapping (const GValue       *value,
-                           const GVariantType *expected_type,
-                           gpointer            user_data)
+                            const GVariantType *expected_type,
+                            gpointer            user_data)
 {
        GVariant *variant = NULL;
        GdkRGBA *color;
@@ -2112,8 +2112,8 @@ _set_overlay_timeout (EogScrollView *view)
 
 static gboolean
 _enter_overlay_event_cb (GtkWidget *widget,
-                        GdkEvent *event,
-                        gpointer user_data)
+                         GdkEvent *event,
+                         gpointer user_data)
 {
        EogScrollView *view = EOG_SCROLL_VIEW (user_data);
 
@@ -2174,14 +2174,14 @@ eog_scroll_view_init (EogScrollView *view)
 
        priv->hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0, 100, 0, 10, 10, 100));
        g_signal_connect (priv->hadj, "value_changed",
-                         G_CALLBACK (adjustment_changed_cb),
-                         view);
+                         G_CALLBACK (adjustment_changed_cb),
+                         view);
 
        priv->hbar = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, priv->hadj);
        priv->vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0, 100, 0, 10, 10, 100));
        g_signal_connect (priv->vadj, "value_changed",
-                         G_CALLBACK (adjustment_changed_cb),
-                         view);
+                         G_CALLBACK (adjustment_changed_cb),
+                         view);
 
        priv->vbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, priv->vadj);
 
@@ -2189,219 +2189,219 @@ eog_scroll_view_init (EogScrollView *view)
        gtk_grid_attach (GTK_GRID (view), priv->overlay, 0, 0, 1, 1);
 
        priv->display = g_object_new (GTK_TYPE_DRAWING_AREA,
-                                     "can-focus", TRUE,
-                                     NULL);
+                                     "can-focus", TRUE,
+                                     NULL);
 
        gtk_widget_add_events (GTK_WIDGET (priv->display),
-                              GDK_EXPOSURE_MASK
-                              | GDK_TOUCHPAD_GESTURE_MASK
-                              | GDK_BUTTON_PRESS_MASK
-                              | GDK_BUTTON_RELEASE_MASK
-                              | GDK_POINTER_MOTION_MASK
-                              | GDK_POINTER_MOTION_HINT_MASK
-                              | GDK_TOUCH_MASK
-                              | GDK_SCROLL_MASK
-                              | GDK_KEY_PRESS_MASK);
+                              GDK_EXPOSURE_MASK
+                              | GDK_TOUCHPAD_GESTURE_MASK
+                              | GDK_BUTTON_PRESS_MASK
+                              | GDK_BUTTON_RELEASE_MASK
+                              | GDK_POINTER_MOTION_MASK
+                              | GDK_POINTER_MOTION_HINT_MASK
+                              | GDK_TOUCH_MASK
+                              | GDK_SCROLL_MASK
+                              | GDK_KEY_PRESS_MASK);
        g_signal_connect (G_OBJECT (priv->display), "configure_event",
-                         G_CALLBACK (display_size_change), view);
+                         G_CALLBACK (display_size_change), view);
        g_signal_connect (G_OBJECT (priv->display), "draw",
-                         G_CALLBACK (display_draw), view);
+                         G_CALLBACK (display_draw), view);
        g_signal_connect (G_OBJECT (priv->display), "map_event",
-                         G_CALLBACK (display_map_event), view);
+                         G_CALLBACK (display_map_event), view);
        g_signal_connect (G_OBJECT (priv->display), "button_press_event",
-                         G_CALLBACK (eog_scroll_view_button_press_event),
-                         view);
+                         G_CALLBACK (eog_scroll_view_button_press_event),
+                         view);
        g_signal_connect (G_OBJECT (priv->display), "motion_notify_event",
-                         G_CALLBACK (eog_scroll_view_motion_event), view);
+                         G_CALLBACK (eog_scroll_view_motion_event), view);
        g_signal_connect (G_OBJECT (priv->display), "button_release_event",
-                         G_CALLBACK (eog_scroll_view_button_release_event),
-                         view);
+                         G_CALLBACK (eog_scroll_view_button_release_event),
+                         view);
        g_signal_connect (G_OBJECT (priv->display), "scroll_event",
-                         G_CALLBACK (eog_scroll_view_scroll_event), view);
+                         G_CALLBACK (eog_scroll_view_scroll_event), view);
        g_signal_connect (G_OBJECT (priv->display), "focus_in_event",
-                         G_CALLBACK (eog_scroll_view_focus_in_event), NULL);
+                         G_CALLBACK (eog_scroll_view_focus_in_event), NULL);
        g_signal_connect (G_OBJECT (priv->display), "focus_out_event",
-                         G_CALLBACK (eog_scroll_view_focus_out_event), NULL);
+                         G_CALLBACK (eog_scroll_view_focus_out_event), NULL);
 
        g_signal_connect (G_OBJECT (view), "key_press_event",
-                         G_CALLBACK (display_key_press_event), view);
+                         G_CALLBACK (display_key_press_event), view);
 
        gtk_drag_source_set (priv->display, GDK_BUTTON1_MASK,
-                            target_table, G_N_ELEMENTS (target_table),
-                            GDK_ACTION_COPY | GDK_ACTION_MOVE |
-                            GDK_ACTION_LINK | GDK_ACTION_ASK);
+                            target_table, G_N_ELEMENTS (target_table),
+                            GDK_ACTION_COPY | GDK_ACTION_MOVE |
+                            GDK_ACTION_LINK | GDK_ACTION_ASK);
        g_signal_connect (G_OBJECT (priv->display), "drag-data-get",
-                         G_CALLBACK (view_on_drag_data_get_cb), view);
+                         G_CALLBACK (view_on_drag_data_get_cb), view);
        g_signal_connect (G_OBJECT (priv->display), "drag-begin",
-                         G_CALLBACK (view_on_drag_begin_cb), view);
+                         G_CALLBACK (view_on_drag_begin_cb), view);
 
        gtk_container_add (GTK_CONTAINER (priv->overlay), priv->display);
 
        gtk_widget_set_hexpand (priv->display, TRUE);
        gtk_widget_set_vexpand (priv->display, TRUE);
        gtk_grid_attach (GTK_GRID (view), priv->hbar,
-                        0, 1, 1, 1);
+                        0, 1, 1, 1);
        gtk_widget_set_hexpand (priv->hbar, TRUE);
        gtk_grid_attach (GTK_GRID (view), priv->vbar,
-                        1, 0, 1, 1);
+                        1, 0, 1, 1);
        gtk_widget_set_vexpand (priv->vbar, TRUE);
 
        g_settings_bind (settings, EOG_CONF_VIEW_USE_BG_COLOR, view,
-                        "use-background-color", G_SETTINGS_BIND_DEFAULT);
+                        "use-background-color", G_SETTINGS_BIND_DEFAULT);
        g_settings_bind_with_mapping (settings, EOG_CONF_VIEW_BACKGROUND_COLOR,
-                                     view, "background-color",
-                                     G_SETTINGS_BIND_DEFAULT,
-                                     sv_string_to_rgba_mapping,
-                                     sv_rgba_to_string_mapping, NULL, NULL);
+                                     view, "background-color",
+                                     G_SETTINGS_BIND_DEFAULT,
+                                     sv_string_to_rgba_mapping,
+                                     sv_rgba_to_string_mapping, NULL, NULL);
        g_settings_bind_with_mapping (settings, EOG_CONF_VIEW_TRANS_COLOR,
-                                     view, "transparency-color",
-                                     G_SETTINGS_BIND_GET,
-                                     sv_string_to_rgba_mapping,
-                                     sv_rgba_to_string_mapping, NULL, NULL);
+                                     view, "transparency-color",
+                                     G_SETTINGS_BIND_GET,
+                                     sv_string_to_rgba_mapping,
+                                     sv_rgba_to_string_mapping, NULL, NULL);
        g_settings_bind (settings, EOG_CONF_VIEW_TRANSPARENCY, view,
-                        "transparency-style", G_SETTINGS_BIND_GET);
+                        "transparency-style", G_SETTINGS_BIND_GET);
        g_settings_bind (settings, EOG_CONF_VIEW_EXTRAPOLATE, view,
-                        "antialiasing-in", G_SETTINGS_BIND_GET);
+                        "antialiasing-in", G_SETTINGS_BIND_GET);
        g_settings_bind (settings, EOG_CONF_VIEW_INTERPOLATE, view,
-                        "antialiasing-out", G_SETTINGS_BIND_GET);
+                        "antialiasing-out", G_SETTINGS_BIND_GET);
 
        g_object_unref (settings);
 
        priv->zoom_gesture = gtk_gesture_zoom_new (GTK_WIDGET (view));
        g_signal_connect (priv->zoom_gesture, "begin",
-                         G_CALLBACK (zoom_gesture_begin_cb), view);
+                         G_CALLBACK (zoom_gesture_begin_cb), view);
        g_signal_connect (priv->zoom_gesture, "update",
-                         G_CALLBACK (zoom_gesture_update_cb), view);
+                         G_CALLBACK (zoom_gesture_update_cb), view);
        g_signal_connect (priv->zoom_gesture, "end",
-                         G_CALLBACK (zoom_gesture_end_cb), view);
+                         G_CALLBACK (zoom_gesture_end_cb), view);
        g_signal_connect (priv->zoom_gesture, "cancel",
-                         G_CALLBACK (zoom_gesture_end_cb), view);
+                         G_CALLBACK (zoom_gesture_end_cb), view);
        gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->zoom_gesture),
-                                                   GTK_PHASE_CAPTURE);
+                                                   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_CALLBACK (rotate_gesture_angle_changed_cb), view);
        g_signal_connect (priv->rotate_gesture, "begin",
-                         G_CALLBACK (rotate_gesture_begin_cb), view);
+                         G_CALLBACK (rotate_gesture_begin_cb), view);
        gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->rotate_gesture),
-                                                   GTK_PHASE_CAPTURE);
+                                                   GTK_PHASE_CAPTURE);
 
        priv->pan_gesture = gtk_gesture_pan_new (GTK_WIDGET (view),
-                                                GTK_ORIENTATION_HORIZONTAL);
+                                                GTK_ORIENTATION_HORIZONTAL);
        g_signal_connect (priv->pan_gesture, "pan",
-                         G_CALLBACK (pan_gesture_pan_cb), view);
+                         G_CALLBACK (pan_gesture_pan_cb), view);
        g_signal_connect (priv->pan_gesture, "end",
-                         G_CALLBACK (pan_gesture_end_cb), view);
-       gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (priv->pan_gesture), 
-                                          TRUE);
+                         G_CALLBACK (pan_gesture_end_cb), view);
+       gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (priv->pan_gesture),
+                                          TRUE);
        gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->pan_gesture),
-                                                   GTK_PHASE_CAPTURE);
+                                                   GTK_PHASE_CAPTURE);
 
        /* left revealer */
        priv->left_revealer = gtk_revealer_new ();
        gtk_revealer_set_transition_type (GTK_REVEALER (priv->left_revealer),
-                                         GTK_REVEALER_TRANSITION_TYPE_CROSSFADE);
+                                         GTK_REVEALER_TRANSITION_TYPE_CROSSFADE);
        gtk_revealer_set_transition_duration (GTK_REVEALER (priv->left_revealer),
-                                             OVERLAY_REVEAL_ANIM_TIME);
+                                             OVERLAY_REVEAL_ANIM_TIME);
        gtk_widget_set_halign (priv->left_revealer, GTK_ALIGN_START);
        gtk_widget_set_valign (priv->left_revealer, GTK_ALIGN_CENTER);
        gtk_widget_set_margin_start(priv->left_revealer, 12);
        gtk_widget_set_margin_end(priv->left_revealer, 12);
        gtk_overlay_add_overlay (GTK_OVERLAY (priv->overlay),
-                                priv->left_revealer);
+                                priv->left_revealer);
 
        /* right revealer */
        priv->right_revealer = gtk_revealer_new ();
        gtk_revealer_set_transition_type (GTK_REVEALER (priv->right_revealer),
-                                         GTK_REVEALER_TRANSITION_TYPE_CROSSFADE);
+                                         GTK_REVEALER_TRANSITION_TYPE_CROSSFADE);
        gtk_revealer_set_transition_duration (GTK_REVEALER (priv->right_revealer),
-                                             OVERLAY_REVEAL_ANIM_TIME);
+                                             OVERLAY_REVEAL_ANIM_TIME);
        gtk_widget_set_halign (priv->right_revealer, GTK_ALIGN_END);
        gtk_widget_set_valign (priv->right_revealer, GTK_ALIGN_CENTER);
        gtk_widget_set_margin_start (priv->right_revealer, 12);
        gtk_widget_set_margin_end (priv->right_revealer, 12);
        gtk_overlay_add_overlay(GTK_OVERLAY (priv->overlay),
-                               priv->right_revealer);
+                               priv->right_revealer);
 
        /* bottom revealer */
        priv->bottom_revealer = gtk_revealer_new ();
        gtk_revealer_set_transition_type (GTK_REVEALER (priv->bottom_revealer),
-                                         GTK_REVEALER_TRANSITION_TYPE_CROSSFADE);
+                                         GTK_REVEALER_TRANSITION_TYPE_CROSSFADE);
        gtk_revealer_set_transition_duration (GTK_REVEALER (priv->bottom_revealer),
-                                             OVERLAY_REVEAL_ANIM_TIME);
+                                             OVERLAY_REVEAL_ANIM_TIME);
        gtk_widget_set_halign (priv->bottom_revealer, GTK_ALIGN_CENTER);
        gtk_widget_set_valign (priv->bottom_revealer, GTK_ALIGN_END);
        gtk_widget_set_margin_bottom (priv->bottom_revealer, 12);
        gtk_overlay_add_overlay (GTK_OVERLAY (priv->overlay),
-                                priv->bottom_revealer);
+                                priv->bottom_revealer);
 
        /* overlaid buttons */
        GtkWidget *button = gtk_button_new_from_icon_name ("go-next-symbolic",
-                                                          GTK_ICON_SIZE_BUTTON);
+                                                          GTK_ICON_SIZE_BUTTON);
 
        gtk_container_add(GTK_CONTAINER (priv->right_revealer), button);
        gtk_actionable_set_action_name(GTK_ACTIONABLE (button), "win.go-next");
        gtk_widget_set_tooltip_text (button,
-                                    _("Go to the next image of the gallery"));
+                                    _("Go to the next image of the gallery"));
        gtk_style_context_add_class (gtk_widget_get_style_context (button),
-                                    GTK_STYLE_CLASS_OSD);
+                                    GTK_STYLE_CLASS_OSD);
 
 
        button = gtk_button_new_from_icon_name("go-previous-symbolic",
-                                              GTK_ICON_SIZE_BUTTON);
+                                              GTK_ICON_SIZE_BUTTON);
 
        gtk_container_add(GTK_CONTAINER (priv->left_revealer), button);
        gtk_actionable_set_action_name (GTK_ACTIONABLE(button),
-                                       "win.go-previous");
+                                       "win.go-previous");
        gtk_widget_set_tooltip_text (button,
-                                    _("Go to the previous image of the gallery"));
+                                    _("Go to the previous image of the gallery"));
        gtk_style_context_add_class (gtk_widget_get_style_context (button),
-                                    GTK_STYLE_CLASS_OSD);
+                                    GTK_STYLE_CLASS_OSD);
 
 
        /* group rotate buttons into a box */
        GtkWidget* bottomBox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
        gtk_style_context_add_class (gtk_widget_get_style_context (bottomBox),
-                                    GTK_STYLE_CLASS_LINKED);
+                                    GTK_STYLE_CLASS_LINKED);
 
        button = gtk_button_new_from_icon_name ("object-rotate-left-symbolic",
-                                               GTK_ICON_SIZE_BUTTON);
+                                               GTK_ICON_SIZE_BUTTON);
        gtk_actionable_set_action_name (GTK_ACTIONABLE (button),
-                                       "win.rotate-270");
+                                       "win.rotate-270");
        gtk_widget_set_tooltip_text (button,
-                                    _("Rotate the image 90 degrees to the left"));
+                                    _("Rotate the image 90 degrees to the left"));
        gtk_style_context_add_class (gtk_widget_get_style_context (button),
-                                    GTK_STYLE_CLASS_OSD);
+                                    GTK_STYLE_CLASS_OSD);
 
        gtk_container_add (GTK_CONTAINER (bottomBox), button);
 
        button = gtk_button_new_from_icon_name ("object-rotate-right-symbolic",
-                                               GTK_ICON_SIZE_BUTTON);
+                                               GTK_ICON_SIZE_BUTTON);
        gtk_actionable_set_action_name (GTK_ACTIONABLE (button),
-                                       "win.rotate-90");
+                                       "win.rotate-90");
        gtk_widget_set_tooltip_text (button,
-                                    _("Rotate the image 90 degrees to the right"));
+                                    _("Rotate the image 90 degrees to the right"));
        gtk_style_context_add_class (gtk_widget_get_style_context (button),
-                                    GTK_STYLE_CLASS_OSD);
+                                    GTK_STYLE_CLASS_OSD);
        gtk_container_add (GTK_CONTAINER (bottomBox), button);
 
        gtk_container_add (GTK_CONTAINER (priv->bottom_revealer), bottomBox);
 
        /* Display overlay buttons on mouse movement */
        g_signal_connect (priv->display,
-                         "motion-notify-event",
-                         G_CALLBACK (_motion_notify_cb),
-                         view);
+                         "motion-notify-event",
+                         G_CALLBACK (_motion_notify_cb),
+                         view);
 
        /* Don't hide overlay buttons when above */
        gtk_widget_add_events (GTK_WIDGET (priv->overlay),
-                              GDK_ENTER_NOTIFY_MASK);
+                              GDK_ENTER_NOTIFY_MASK);
        g_signal_connect (priv->overlay,
-                         "enter-notify-event",
-                         G_CALLBACK (_enter_overlay_event_cb),
-                         view);
+                         "enter-notify-event",
+                         G_CALLBACK (_enter_overlay_event_cb),
+                         view);
 }
 
 static void
@@ -2460,7 +2460,7 @@ eog_scroll_view_dispose (GObject *object)
 
 static void
 eog_scroll_view_get_property (GObject *object, guint property_id,
-                             GValue *value, GParamSpec *pspec)
+                              GValue *value, GParamSpec *pspec)
 {
        EogScrollView *view;
        EogScrollViewPrivate *priv;
@@ -2512,7 +2512,7 @@ eog_scroll_view_get_property (GObject *object, guint property_id,
 
 static void
 eog_scroll_view_set_property (GObject *object, guint property_id,
-                             const GValue *value, GParamSpec *pspec)
+                              const GValue *value, GParamSpec *pspec)
 {
        EogScrollView *view;
 
@@ -2570,8 +2570,8 @@ eog_scroll_view_class_init (EogScrollViewClass *klass)
        widget_class = (GtkWidgetClass*) klass;
 
        gobject_class->dispose = eog_scroll_view_dispose;
-        gobject_class->set_property = eog_scroll_view_set_property;
-        gobject_class->get_property = eog_scroll_view_get_property;
+       gobject_class->set_property = eog_scroll_view_set_property;
+       gobject_class->get_property = eog_scroll_view_get_property;
 
        /**
         * EogScrollView:antialiasing-in:
@@ -2580,9 +2580,9 @@ eog_scroll_view_class_init (EogScrollViewClass *klass)
         * while being zoomed in.
         */
        g_object_class_install_property (
-               gobject_class, PROP_ANTIALIAS_IN,
-               g_param_spec_boolean ("antialiasing-in", NULL, NULL, TRUE,
-                                     G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
+               gobject_class, PROP_ANTIALIAS_IN,
+               g_param_spec_boolean ("antialiasing-in", NULL, NULL, TRUE,
+                                     G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
        /**
         * EogScrollView:antialiasing-out:
         *
@@ -2590,9 +2590,9 @@ eog_scroll_view_class_init (EogScrollViewClass *klass)
         * while being zoomed out.
         */
        g_object_class_install_property (
-               gobject_class, PROP_ANTIALIAS_OUT,
-               g_param_spec_boolean ("antialiasing-out", NULL, NULL, TRUE,
-                                     G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
+               gobject_class, PROP_ANTIALIAS_OUT,
+               g_param_spec_boolean ("antialiasing-out", NULL, NULL, TRUE,
+                                     G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
 
        /**
         * EogScrollView:background-color:
@@ -2602,15 +2602,15 @@ eog_scroll_view_class_init (EogScrollViewClass *klass)
         * active GTK theme.
         */
        g_object_class_install_property (
-               gobject_class, PROP_BACKGROUND_COLOR,
-               g_param_spec_boxed ("background-color", NULL, NULL,
-                                   GDK_TYPE_RGBA,
-                                   G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
+               gobject_class, PROP_BACKGROUND_COLOR,
+               g_param_spec_boxed ("background-color", NULL, NULL,
+                                   GDK_TYPE_RGBA,
+                                   G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
 
        g_object_class_install_property (
-               gobject_class, PROP_USE_BG_COLOR,
-               g_param_spec_boolean ("use-background-color", NULL, NULL, FALSE,
-                                     G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
+               gobject_class, PROP_USE_BG_COLOR,
+               g_param_spec_boolean ("use-background-color", NULL, NULL, FALSE,
+                                     G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
 
        /**
         * EogScrollView:zoom-multiplier:
@@ -2619,10 +2619,10 @@ eog_scroll_view_class_init (EogScrollViewClass *klass)
         * scrolling with the scrollwheel to determine the next zoom factor.
         */
        g_object_class_install_property (
-               gobject_class, PROP_ZOOM_MULTIPLIER,
-               g_param_spec_double ("zoom-multiplier", NULL, NULL,
-                                    -G_MAXDOUBLE, G_MAXDOUBLE - 1.0, 0.05,
-                                    G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
+               gobject_class, PROP_ZOOM_MULTIPLIER,
+               g_param_spec_double ("zoom-multiplier", NULL, NULL,
+                                    -G_MAXDOUBLE, G_MAXDOUBLE - 1.0, 0.05,
+                                    G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
 
        /**
         * EogScrollView:scrollwheel-zoom:
@@ -2631,9 +2631,9 @@ eog_scroll_view_class_init (EogScrollViewClass *klass)
         * used for scrolling a zoomed image.
         */
        g_object_class_install_property (
-               gobject_class, PROP_SCROLLWHEEL_ZOOM,
-               g_param_spec_boolean ("scrollwheel-zoom", NULL, NULL, TRUE,
-                                     G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
+               gobject_class, PROP_SCROLLWHEEL_ZOOM,
+               g_param_spec_boolean ("scrollwheel-zoom", NULL, NULL, TRUE,
+                                     G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
 
        /**
         * EogScrollView:image:
@@ -2641,9 +2641,9 @@ eog_scroll_view_class_init (EogScrollViewClass *klass)
         * This is the currently display #EogImage.
         */
        g_object_class_install_property (
-               gobject_class, PROP_IMAGE,
-               g_param_spec_object ("image", NULL, NULL, EOG_TYPE_IMAGE,
-                                    G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
+               gobject_class, PROP_IMAGE,
+               g_param_spec_object ("image", NULL, NULL, EOG_TYPE_IMAGE,
+                                    G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
 
        /**
         * EogScrollView:transparency-color:
@@ -2652,73 +2652,73 @@ eog_scroll_view_class_init (EogScrollViewClass *klass)
         * if #EogScrollView:transparency-style is set to %EOG_TRANSP_COLOR.
         */
        g_object_class_install_property (
-               gobject_class, PROP_TRANSP_COLOR,
-               g_param_spec_boxed ("transparency-color", NULL, NULL,
-                                   GDK_TYPE_RGBA,
-                                   G_PARAM_WRITABLE | G_PARAM_STATIC_NAME));
-       
+               gobject_class, PROP_TRANSP_COLOR,
+               g_param_spec_boxed ("transparency-color", NULL, NULL,
+                                   GDK_TYPE_RGBA,
+                                   G_PARAM_WRITABLE | G_PARAM_STATIC_NAME));
+
        /**
         * EogScrollView:transparency-style:
         *
         * Determines how to fill the shown image's transparent areas.
         */
        g_object_class_install_property (
-               gobject_class, PROP_TRANSPARENCY_STYLE,
-               g_param_spec_enum ("transparency-style", NULL, NULL,
-                                  EOG_TYPE_TRANSPARENCY_STYLE,
-                                  EOG_TRANSP_CHECKED,
-                                  G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
+               gobject_class, PROP_TRANSPARENCY_STYLE,
+               g_param_spec_enum ("transparency-style", NULL, NULL,
+                                  EOG_TYPE_TRANSPARENCY_STYLE,
+                                  EOG_TRANSP_CHECKED,
+                                  G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
 
        g_object_class_install_property (
-               gobject_class, PROP_ZOOM_MODE,
-               g_param_spec_enum ("zoom-mode", NULL, NULL,
-                                  EOG_TYPE_ZOOM_MODE,
-                                  EOG_ZOOM_MODE_SHRINK_TO_FIT,
-                                  G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
+               gobject_class, PROP_ZOOM_MODE,
+               g_param_spec_enum ("zoom-mode", NULL, NULL,
+                                  EOG_TYPE_ZOOM_MODE,
+                                  EOG_ZOOM_MODE_SHRINK_TO_FIT,
+                                  G_PARAM_READWRITE | G_PARAM_STATIC_NAME));
 
        view_signals [SIGNAL_ZOOM_CHANGED] =
-               g_signal_new ("zoom_changed",
-                             EOG_TYPE_SCROLL_VIEW,
-                             G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (EogScrollViewClass, zoom_changed),
-                             NULL, NULL,
-                             g_cclosure_marshal_VOID__DOUBLE,
-                             G_TYPE_NONE, 1,
-                             G_TYPE_DOUBLE);
+               g_signal_new ("zoom_changed",
+                             EOG_TYPE_SCROLL_VIEW,
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (EogScrollViewClass, zoom_changed),
+                             NULL, NULL,
+                             g_cclosure_marshal_VOID__DOUBLE,
+                             G_TYPE_NONE, 1,
+                             G_TYPE_DOUBLE);
        view_signals [SIGNAL_ROTATION_CHANGED] =
-               g_signal_new ("rotation-changed",
-                             EOG_TYPE_SCROLL_VIEW,
-                             G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (EogScrollViewClass, rotation_changed),
-                             NULL, NULL,
-                             g_cclosure_marshal_VOID__DOUBLE,
-                             G_TYPE_NONE, 1,
-                             G_TYPE_DOUBLE);
+               g_signal_new ("rotation-changed",
+                             EOG_TYPE_SCROLL_VIEW,
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (EogScrollViewClass, rotation_changed),
+                             NULL, NULL,
+                             g_cclosure_marshal_VOID__DOUBLE,
+                             G_TYPE_NONE, 1,
+                             G_TYPE_DOUBLE);
 
        view_signals [SIGNAL_NEXT_IMAGE] =
-               g_signal_new ("next-image",
-                             EOG_TYPE_SCROLL_VIEW,
-                             G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (EogScrollViewClass, next_image),
-                             NULL, NULL,
-                             g_cclosure_marshal_VOID__VOID,
-                             G_TYPE_NONE, 0);
+               g_signal_new ("next-image",
+                             EOG_TYPE_SCROLL_VIEW,
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (EogScrollViewClass, next_image),
+                             NULL, NULL,
+                             g_cclosure_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
        view_signals [SIGNAL_PREVIOUS_IMAGE] =
-               g_signal_new ("previous-image",
-                             EOG_TYPE_SCROLL_VIEW,
-                             G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (EogScrollViewClass, previous_image),
-                             NULL, NULL,
-                             g_cclosure_marshal_VOID__VOID,
-                             G_TYPE_NONE, 0);
+               g_signal_new ("previous-image",
+                             EOG_TYPE_SCROLL_VIEW,
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (EogScrollViewClass, previous_image),
+                             NULL, NULL,
+                             g_cclosure_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
 
        widget_class->size_allocate = eog_scroll_view_size_allocate;
 }
 
 static void
 view_on_drag_begin_cb (GtkWidget        *widget,
-                      GdkDragContext   *context,
-                      gpointer          user_data)
+                       GdkDragContext   *context,
+                       gpointer          user_data)
 {
        EogScrollView *view;
        EogImage *image;
@@ -2740,11 +2740,11 @@ view_on_drag_begin_cb (GtkWidget        *widget,
 
 static void
 view_on_drag_data_get_cb (GtkWidget        *widget,
-                         GdkDragContext   *drag_context,
-                         GtkSelectionData *data,
-                         guint             info,
-                         guint             time,
-                         gpointer          user_data)
+                          GdkDragContext   *drag_context,
+                          GtkSelectionData *data,
+                          guint             info,
+                          guint             time,
+                          gpointer          user_data)
 {
        EogScrollView *view;
        EogImage *image;
@@ -2771,10 +2771,10 @@ eog_scroll_view_new (void)
        GtkWidget *widget;
 
        widget = g_object_new (EOG_TYPE_SCROLL_VIEW,
-                              "can-focus", TRUE,
-                              "row-homogeneous", FALSE,
-                              "column-homogeneous", FALSE,
-                              NULL);
+                              "can-focus", TRUE,
+                              "row-homogeneous", FALSE,
+                              "column-homogeneous", FALSE,
+                              NULL);
 
        return widget;
 }
@@ -2788,7 +2788,7 @@ eog_scroll_view_popup_menu (EogScrollView *view, GdkEventButton *event)
 
 static gboolean
 view_on_button_press_event_cb (GtkWidget *view, GdkEventButton *event,
-                              gpointer user_data)
+                               gpointer user_data)
 {
        /* Ignore double-clicks and triple-clicks */
        if (gdk_event_triggers_context_menu ((const GdkEvent*) event)
@@ -2811,7 +2811,7 @@ eog_scroll_view_popup_menu_handler (GtkWidget *widget, gpointer user_data)
 
 void
 eog_scroll_view_set_popup (EogScrollView *view,
-                          GtkMenu *menu)
+                           GtkMenu *menu)
 {
        g_return_if_fail (EOG_IS_SCROLL_VIEW (view));
        g_return_if_fail (view->priv->menu == NULL);
@@ -2819,13 +2819,13 @@ eog_scroll_view_set_popup (EogScrollView *view,
        view->priv->menu = g_object_ref (menu);
 
        gtk_menu_attach_to_widget (GTK_MENU (view->priv->menu),
-                                  GTK_WIDGET (view),
-                                  NULL);
+                                  GTK_WIDGET (view),
+                                  NULL);
 
        g_signal_connect (G_OBJECT (view), "button_press_event",
-                         G_CALLBACK (view_on_button_press_event_cb), NULL);
+                         G_CALLBACK (view_on_button_press_event_cb), NULL);
        g_signal_connect (G_OBJECT (view), "popup-menu",
-                         G_CALLBACK (eog_scroll_view_popup_menu_handler), NULL);
+                         G_CALLBACK (eog_scroll_view_popup_menu_handler), NULL);
 }
 
 static gboolean
@@ -2871,7 +2871,7 @@ _eog_scroll_view_update_bg_color (EogScrollView *view)
 
 void
 eog_scroll_view_set_background_color (EogScrollView *view,
-                                     const GdkRGBA *color)
+                                      const GdkRGBA *color)
 {
        g_return_if_fail (EOG_IS_SCROLL_VIEW (view));
 
@@ -2881,7 +2881,7 @@ eog_scroll_view_set_background_color (EogScrollView *view,
 
 void
 eog_scroll_view_override_bg_color (EogScrollView *view,
-                                  const GdkRGBA *color)
+                                   const GdkRGBA *color)
 {
        g_return_if_fail (EOG_IS_SCROLL_VIEW (view));
 
@@ -2909,23 +2909,23 @@ eog_scroll_view_set_use_bg_color (EogScrollView *view, gboolean use)
 
 void
 eog_scroll_view_set_scroll_wheel_zoom (EogScrollView *view,
-                                      gboolean       scroll_wheel_zoom)
+                                       gboolean       scroll_wheel_zoom)
 {
        g_return_if_fail (EOG_IS_SCROLL_VIEW (view));
 
        if (view->priv->scroll_wheel_zoom != scroll_wheel_zoom) {
-               view->priv->scroll_wheel_zoom = scroll_wheel_zoom;
+               view->priv->scroll_wheel_zoom = scroll_wheel_zoom;
                g_object_notify (G_OBJECT (view), "scrollwheel-zoom");
        }
 }
 
 void
 eog_scroll_view_set_zoom_multiplier (EogScrollView *view,
-                                    gdouble        zoom_multiplier)
+                                     gdouble        zoom_multiplier)
 {
        g_return_if_fail (EOG_IS_SCROLL_VIEW (view));
 
-        view->priv->zoom_multiplier = 1.0 + zoom_multiplier;
+       view->priv->zoom_multiplier = 1.0 + zoom_multiplier;
 
        g_object_notify (G_OBJECT (view), "zoom-multiplier");
 }
@@ -2941,7 +2941,7 @@ _set_zoom_mode_internal (EogScrollView *view, EogZoomMode mode)
                eog_scroll_view_zoom_fit (view);
        else
                view->priv->zoom_mode = mode;
-       
+
        if (notify)
                g_object_notify (G_OBJECT (view), "zoom-mode");
 }
@@ -2962,7 +2962,7 @@ EogZoomMode
 eog_scroll_view_get_zoom_mode (EogScrollView *view)
 {
        g_return_val_if_fail (EOG_IS_SCROLL_VIEW (view),
-                             EOG_ZOOM_MODE_SHRINK_TO_FIT);
+                             EOG_ZOOM_MODE_SHRINK_TO_FIT);
 
        return view->priv->zoom_mode;
 }
@@ -3036,7 +3036,7 @@ eog_scroll_view_event_is_over_image (EogScrollView *view, const GdkEvent *ev)
        priv = view->priv;
        window = gtk_widget_get_window (GTK_WIDGET (priv->display));
 
-       if (G_UNLIKELY (priv->pixbuf == NULL 
+       if (G_UNLIKELY (priv->pixbuf == NULL
            || window != ((GdkEventAny*) ev)->window))
                return FALSE;
 
diff --git a/src/eog-scroll-view.h b/src/eog-scroll-view.h
index 2b3c1da..063ce81 100644
--- a/src/eog-scroll-view.h
+++ b/src/eog-scroll-view.h
@@ -62,6 +62,9 @@ typedef enum {
        EOG_ZOOM_MODE_SHRINK_TO_FIT
 } EogZoomMode;
 
+#define EOG_SCROLL_VIEW_MAX_ZOOM_FACTOR (20)
+#define EOG_SCROLL_VIEW_MIN_ZOOM_FACTOR (0.02)
+
 GType    eog_scroll_view_get_type         (void) G_GNUC_CONST;
 GtkWidget* eog_scroll_view_new            (void);
 
diff --git a/src/eog-window.c b/src/eog-window.c
index ae9d7ca..81eff17 100644
--- a/src/eog-window.c
+++ b/src/eog-window.c
@@ -56,6 +56,7 @@
 #include "eog-clipboard-handler.h"
 #include "eog-window-activatable.h"
 #include "eog-metadata-sidebar.h"
+#include "eog-zoom-entry.h"
 
 #include "eog-enum-types.h"
 
@@ -131,8 +132,6 @@ struct _EogWindowPrivate {
         GtkWidget           *statusbar;
         GtkWidget           *nav;
        GtkWidget           *message_area;
-       GtkWidget           *zoom_revealer;
-       GtkWidget           *zoom_scale;
        GtkWidget           *properties_dlg;
 
        GMenu               *open_with_menu;
@@ -204,8 +203,6 @@ static void eog_window_list_store_image_removed (GtkTreeModel *tree_model,
 static void eog_window_set_wallpaper (EogWindow *window, const gchar *filename, const gchar 
*visible_filename);
 static gboolean eog_window_save_images (EogWindow *window, GList *images);
 static void eog_window_finish_saving (EogWindow *window);
-static void eog_window_zoom_scale_value_changed_cb (GtkRange *range,
-                                                   gpointer user_data);
 static void eog_window_error_message_area_response (GtkInfoBar *message_area,
                                                    gint        response_id,
                                                    EogWindow  *window);
@@ -234,21 +231,6 @@ _eog_zoom_shrink_to_boolean (GBinding *binding, const GValue *source,
        return TRUE;
 }
 
-static gboolean
-_eog_zoom_button_variant_to_boolean (GBinding *binding, const GValue *source,
-                                    GValue *target, gpointer user_data)
-{
-       GVariant *variant = g_value_get_variant (source);
-       g_return_val_if_fail(g_variant_is_of_type (variant,
-                                                  G_VARIANT_TYPE_BOOLEAN),
-                            FALSE);
-
-       // Use inverted logic, as the button behaves inverted as well
-       g_value_set_boolean(target, !g_variant_get_boolean(variant));
-
-       return TRUE;
-}
-
 static void
 eog_window_set_gallery_mode (EogWindow           *window,
                             EogWindowGalleryPos  position,
@@ -496,19 +478,6 @@ eog_window_get_display_profile (GtkWidget *window)
 #endif
 
 static void
-update_zoom_scale (EogWindow *window)
-{
-       EogWindowPrivate *priv;
-       gdouble zoom;
-
-       g_return_if_fail (EOG_IS_WINDOW (window));
-
-       priv = window->priv;
-       zoom = eog_scroll_view_get_zoom (EOG_SCROLL_VIEW (priv->view));
-       gtk_range_set_value (GTK_RANGE (priv->zoom_scale), zoom);
-}
-
-static void
 update_image_pos (EogWindow *window)
 {
        EogWindowPrivate *priv;
@@ -1633,19 +1602,6 @@ view_zoom_changed_cb (GtkWidget *widget, double zoom, gpointer user_data)
 
        update_status_bar (window);
 
-       /* Block signal handler to avoid setting the zoom again.
-        * Although the ScrollView will usually ignore it, it won't
-        * do so when the zoom scale clamps the zoom factor to its
-        * own allowed range. (#747410)
-        */
-       g_signal_handlers_block_by_func (window->priv->zoom_scale,
-                                        eog_window_zoom_scale_value_changed_cb,
-                                        window);
-       update_zoom_scale (window);
-       g_signal_handlers_unblock_by_func (window->priv->zoom_scale,
-                                          eog_window_zoom_scale_value_changed_cb,
-                                          window);
-
        action_zoom_in =
                g_action_map_lookup_action (G_ACTION_MAP (window),
                                             "zoom-in");
@@ -4214,60 +4170,6 @@ eog_window_view_previous_image_cb (EogScrollView *view,
 }
 
 static void
-eog_window_zoom_scale_value_changed_cb (GtkRange *range, gpointer user_data)
-{
-       EogWindow *window;
-       EogWindowPrivate *priv;
-
-       g_return_if_fail (EOG_IS_WINDOW (user_data));
-       window = EOG_WINDOW (user_data);
-       priv = window->priv;
-
-       if (priv->view) {
-               gdouble value;
-
-               value = gtk_range_get_value (range);
-               eog_scroll_view_set_zoom (EOG_SCROLL_VIEW (priv->view), value);
-       }
-}
-
-static void
-eog_window_zoom_button_toggled_cb (GtkToggleButton *button, gpointer user_data)
-{
-       EogWindow *window;
-       EogWindowPrivate *priv;
-       GtkWidget *zoom_image;
-       gboolean toggled;
-
-       g_return_if_fail (EOG_IS_WINDOW (user_data));
-       window = EOG_WINDOW (user_data);
-       priv = window->priv;
-
-       if (!priv->view) {
-               return;
-       }
-
-       toggled = gtk_toggle_button_get_active (button);
-       if (toggled) {
-               zoom_image = gtk_image_new_from_icon_name ("zoom-out-symbolic",
-                                                          GTK_ICON_SIZE_BUTTON);
-               gtk_widget_set_tooltip_text (GTK_WIDGET (button),
-                                            _("Fit the image to the window"));
-               eog_scroll_view_zoom_in (EOG_SCROLL_VIEW (priv->view), FALSE);
-       } else {
-               zoom_image = gtk_image_new_from_icon_name ("zoom-in-symbolic",
-                                                          GTK_ICON_SIZE_BUTTON);
-               eog_scroll_view_set_zoom_mode (EOG_SCROLL_VIEW (priv->view),
-                                              EOG_ZOOM_MODE_SHRINK_TO_FIT);
-               gtk_widget_set_tooltip_text (GTK_WIDGET (button),
-                                            _("Shrink or enlarge the current image"));
-       }
-
-       gtk_revealer_set_reveal_child (GTK_REVEALER (priv->zoom_revealer), toggled);
-       gtk_button_set_image (GTK_BUTTON (button), zoom_image);
-}
-
-static void
 eog_window_construct_ui (EogWindow *window)
 {
        EogWindowPrivate *priv;
@@ -4279,8 +4181,7 @@ eog_window_construct_ui (EogWindow *window)
        GtkWidget *popup_menu;
        GtkWidget *hpaned;
        GtkWidget *headerbar;
-       GtkWidget *zoom_button;
-       GtkWidget *zoom_image;
+       GtkWidget *zoom_entry;
        GtkWidget *menu_button;
        GtkWidget *menu_image;
        GtkWidget *fullscreen_button;
@@ -4300,6 +4201,7 @@ eog_window_construct_ui (EogWindow *window)
        gtk_window_set_titlebar (GTK_WINDOW (window), headerbar);
        gtk_widget_show (headerbar);
 
+#if 0
        zoom_button = gtk_toggle_button_new ();
        zoom_image = gtk_image_new_from_icon_name ("zoom-in-symbolic",
                                                   GTK_ICON_SIZE_BUTTON);
@@ -4339,6 +4241,7 @@ eog_window_construct_ui (EogWindow *window)
        gtk_container_add (GTK_CONTAINER (priv->zoom_revealer),
                           priv->zoom_scale);
        gtk_widget_show (priv->zoom_scale);
+#endif
 
        menu_button = gtk_menu_button_new ();
        menu_image = gtk_image_new_from_icon_name ("open-menu-symbolic",
@@ -4457,11 +4360,6 @@ eog_window_construct_ui (EogWindow *window)
                                             G_BINDING_SYNC_CREATE,
                                             _eog_zoom_shrink_to_boolean,
                                             NULL, NULL, NULL);
-               g_object_bind_property_full (action, "state",
-                                            zoom_button, "active",
-                                            G_BINDING_SYNC_CREATE,
-                                            _eog_zoom_button_variant_to_boolean,
-                                            NULL, NULL, NULL);
        }
        g_settings_bind (priv->view_settings, EOG_CONF_VIEW_SCROLL_WHEEL_ZOOM,
                         priv->view, "scrollwheel-zoom", G_SETTINGS_BIND_GET);
@@ -4492,6 +4390,11 @@ eog_window_construct_ui (EogWindow *window)
 
        gtk_widget_show_all (hpaned);
 
+       zoom_entry = eog_zoom_entry_new (EOG_SCROLL_VIEW (priv->view),
+                                        G_MENU (gtk_builder_get_object (builder,
+                                                                        "zoom-menu")));
+       gtk_header_bar_pack_start (GTK_HEADER_BAR (headerbar), zoom_entry);
+
        priv->thumbview = g_object_ref (eog_thumb_view_new ());
 
        /* giving shape to the view */
diff --git a/src/eog-zoom-entry.c b/src/eog-zoom-entry.c
new file mode 100644
index 0000000..908f4ef
--- /dev/null
+++ b/src/eog-zoom-entry.c
@@ -0,0 +1,335 @@
+/*
+ * eog-zoom-entry.c
+ * This file is part of eog
+ *
+ * Author: Felix Riemann <friemann gnome org>
+ *
+ * Copyright (C) 2017 GNOME Foundation
+ *
+ * Based on code (ev-zoom-action.c) by:
+ *      - Carlos Garcia Campos <carlosgc gnome org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "eog-zoom-entry.h"
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <math.h>
+
+enum {
+       PROP_0,
+       PROP_SCROLL_VIEW,
+       PROP_MENU
+};
+
+typedef struct _EogZoomEntryPrivate {
+       GtkWidget *btn_zoom_in;
+       GtkWidget *btn_zoom_out;
+       GtkWidget *value_entry;
+
+       EogScrollView *view;
+
+       GMenu *menu;
+       GMenuModel *zoom_free_section;
+       GtkWidget       *popup;
+       gboolean         popup_shown;
+} EogZoomEntryPrivate;
+
+struct _EogZoomEntry {
+       GtkBox box;
+
+       EogZoomEntryPrivate *priv;
+};
+
+static const struct {
+       const gchar *name;
+       const double level;
+} zoom_levels[] = {
+       { N_("33%"), (1.0/3.0) },
+       { N_("50%"), (1.0/2.0) },
+       { N_("100%"), 1.0 },
+       { N_("133%"), (1.0/0.75) },
+       { N_("200%"), 2.0 },
+       { N_("500%"), 5.0 },
+       { N_("1000%"), 10.0 },
+       { N_("1500%"), 15.0 },
+       { N_("2000%"), 20.0 }
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (EogZoomEntry, eog_zoom_entry, GTK_TYPE_BOX);
+
+//static guint signals[LAST_SIGNAL] = { 0 };
+
+static void eog_zoom_entry_reset_zoom_level (EogZoomEntry *entry);
+static void eog_zoom_entry_set_zoom_level (EogZoomEntry *entry, gdouble zoom);
+
+
+static void
+eog_zoom_entry_populate_free_zoom_section (EogZoomEntry *zoom_entry)
+{
+       guint   i;
+       gint    width = 0;
+
+       for (i = 0; i < G_N_ELEMENTS (zoom_levels); i++) {
+               GMenuItem *item;
+               gint       length;
+
+               if (zoom_levels[i].level > EOG_SCROLL_VIEW_MAX_ZOOM_FACTOR)
+                       break;
+
+               length = g_utf8_strlen (zoom_levels[i].name, -1);
+               if (length > width)
+                       width = length;
+
+               item = g_menu_item_new (zoom_levels[i].name, NULL);
+               g_menu_item_set_action_and_target (item, "win.zoom-set",
+                                                  "d", zoom_levels[i].level);
+               g_menu_append_item (G_MENU (zoom_entry->priv->zoom_free_section), item);
+               g_object_unref (item);
+       }
+}
+
+static void
+eog_zoom_entry_activate_cb (GtkEntry *gtk_entry, EogZoomEntry *entry)
+{
+       const gchar *text = gtk_entry_get_text (gtk_entry);
+       gchar *end_ptr = NULL;
+       double zoom_perc;
+
+       if (!text || text[0] == '\0') {
+               eog_zoom_entry_reset_zoom_level (entry);
+               return;
+       }
+
+       zoom_perc = g_strtod (text, &end_ptr);
+       if (end_ptr && end_ptr[0] != '\0' && end_ptr[0] != '%') {
+               eog_zoom_entry_reset_zoom_level (entry);
+               return;
+       }
+
+       eog_scroll_view_set_zoom (entry->priv->view, zoom_perc / 100.0);
+}
+
+static gboolean
+focus_out_cb (EogZoomEntry *zoom_entry)
+{
+       eog_zoom_entry_reset_zoom_level (zoom_entry);
+
+       return FALSE;
+}
+
+static void
+popup_menu_closed (GtkWidget    *popup,
+                   EogZoomEntry *zoom_entry)
+{
+       if (zoom_entry->priv->popup != popup)
+               return;
+
+       zoom_entry->priv->popup_shown = FALSE;
+       zoom_entry->priv->popup = NULL;
+}
+
+static GtkWidget*
+get_popup (EogZoomEntry *zoom_entry)
+{
+       GdkRectangle rect;
+
+       if (zoom_entry->priv->popup)
+               return zoom_entry->priv->popup;
+
+       zoom_entry->priv->popup = gtk_popover_new_from_model (GTK_WIDGET (zoom_entry),
+                                                              G_MENU_MODEL (zoom_entry->priv->menu));
+       g_signal_connect (zoom_entry->priv->popup, "closed",
+                         G_CALLBACK (popup_menu_closed),
+                         zoom_entry);
+       gtk_entry_get_icon_area (GTK_ENTRY (zoom_entry->priv->value_entry),
+                                GTK_ENTRY_ICON_SECONDARY, &rect);
+       gtk_popover_set_pointing_to (GTK_POPOVER (zoom_entry->priv->popup), &rect);
+       gtk_popover_set_position (GTK_POPOVER (zoom_entry->priv->popup), GTK_POS_BOTTOM);
+
+       return zoom_entry->priv->popup;
+}
+
+static void
+eog_zoom_entry_icon_press_cb (GtkEntry *entry, GtkEntryIconPosition icon_pos,
+                              GdkEvent *event, gpointer data)
+{
+       EogZoomEntry *zoom_entry;
+       guint button;
+
+       g_return_if_fail (EOG_IS_ZOOM_ENTRY (data));
+       g_return_if_fail (icon_pos == GTK_ENTRY_ICON_SECONDARY);
+
+       if (!gdk_event_get_button (event, &button) || button != GDK_BUTTON_PRIMARY)
+               return;
+
+       zoom_entry = EOG_ZOOM_ENTRY (data);
+
+       gtk_widget_show (get_popup (zoom_entry));
+       zoom_entry->priv->popup_shown = TRUE;
+}
+
+static void
+eog_zoom_entry_view_zoom_changed_cb (EogScrollView *view, gdouble zoom,
+                                     gpointer data)
+{
+       EogZoomEntry *zoom_entry = EOG_ZOOM_ENTRY (data);
+
+       eog_zoom_entry_set_zoom_level (zoom_entry, zoom);
+}
+
+static void
+eog_zoom_entry_constructed (GObject *object)
+{
+       EogZoomEntry *zoom_entry = EOG_ZOOM_ENTRY (object);
+
+       G_OBJECT_CLASS (eog_zoom_entry_parent_class)->constructed (object);
+
+       g_signal_connect (zoom_entry->priv->view,
+                         "zoom-changed",
+                         G_CALLBACK (eog_zoom_entry_view_zoom_changed_cb),
+                         zoom_entry);
+
+       zoom_entry->priv->zoom_free_section =
+                       g_menu_model_get_item_link (G_MENU_MODEL (zoom_entry->priv->menu),
+                                                   1, G_MENU_LINK_SECTION);
+       eog_zoom_entry_populate_free_zoom_section (zoom_entry);
+}
+
+static void
+eog_zoom_entry_finalize (GObject *object)
+{
+       EogZoomEntry *zoom_entry = EOG_ZOOM_ENTRY (object);
+
+       g_clear_object (&zoom_entry->priv->menu);
+       g_clear_object (&zoom_entry->priv->zoom_free_section);
+       g_clear_object (&zoom_entry->priv->view);
+
+       G_OBJECT_CLASS (eog_zoom_entry_parent_class)->finalize (object);
+}
+
+static void
+eog_zoom_entry_set_property (GObject      *object,
+                             guint         prop_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+       EogZoomEntry *zoom_entry = EOG_ZOOM_ENTRY (object);
+
+       switch (prop_id) {
+       case PROP_SCROLL_VIEW:
+               zoom_entry->priv->view = g_value_dup_object (value);
+               break;
+       case PROP_MENU:
+               zoom_entry->priv->menu = g_value_dup_object (value);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       }
+}
+
+static void
+eog_zoom_entry_set_zoom_level (EogZoomEntry *entry, gdouble zoom)
+{
+       gchar *zoom_str;
+       gdouble zoom_percent;
+
+       /* Mimic the zoom calculation from EogWindow to get matching displays */
+       zoom = CLAMP (zoom, EOG_SCROLL_VIEW_MIN_ZOOM_FACTOR,
+                     EOG_SCROLL_VIEW_MAX_ZOOM_FACTOR);
+       zoom_percent = floor (zoom * 100. + 0.5);
+       zoom_str = g_strdup_printf ("%d%%", (gint) zoom_percent);
+       gtk_entry_set_text (GTK_ENTRY (entry->priv->value_entry), zoom_str);
+       g_free (zoom_str);
+}
+
+static void
+eog_zoom_entry_reset_zoom_level (EogZoomEntry *entry)
+{
+       const gdouble zoom = eog_scroll_view_get_zoom (entry->priv->view);
+       eog_zoom_entry_set_zoom_level (entry, zoom);
+}
+
+static void
+eog_zoom_entry_class_init (EogZoomEntryClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       GtkWidgetClass *wklass = GTK_WIDGET_CLASS (klass);
+
+       object_class->constructed = eog_zoom_entry_constructed;
+       object_class->set_property = eog_zoom_entry_set_property;
+       object_class->finalize = eog_zoom_entry_finalize;
+
+       gtk_widget_class_set_template_from_resource (wklass,
+                                                    "/org/gnome/eog/ui/eog-zoom-entry.ui");
+       gtk_widget_class_bind_template_child_private (wklass,
+                                                     EogZoomEntry,
+                                                     btn_zoom_in);
+       gtk_widget_class_bind_template_child_private (wklass,
+                                                     EogZoomEntry,
+                                                     btn_zoom_out);
+       gtk_widget_class_bind_template_child_private (wklass,
+                                                     EogZoomEntry,
+                                                     value_entry);
+
+       gtk_widget_class_bind_template_callback (wklass,
+                                                eog_zoom_entry_activate_cb);
+       gtk_widget_class_bind_template_callback (wklass,
+                                                eog_zoom_entry_icon_press_cb);
+
+       g_object_class_install_property (object_class, PROP_SCROLL_VIEW,
+                                        g_param_spec_object ("scroll-view",
+                                                             "EogScrollView",
+                                                             "The EogScrollView to work with",
+                                                             EOG_TYPE_SCROLL_VIEW,
+                                                             G_PARAM_WRITABLE |
+                                                             G_PARAM_CONSTRUCT_ONLY |
+                                                             G_PARAM_STATIC_STRINGS));
+
+       g_object_class_install_property (object_class, PROP_MENU,
+                                        g_param_spec_object ("menu",
+                                                             "Menu",
+                                                             "The zoom popup menu",
+                                                             G_TYPE_MENU,
+                                                             G_PARAM_WRITABLE |
+                                                             G_PARAM_CONSTRUCT_ONLY |
+                                                             G_PARAM_STATIC_STRINGS));
+}
+
+static void
+eog_zoom_entry_init (EogZoomEntry *entry)
+{
+       entry->priv = eog_zoom_entry_get_instance_private (entry);
+       gtk_widget_init_template (GTK_WIDGET (entry));
+
+       g_signal_connect_swapped (entry->priv->value_entry, "focus-out-event",
+                                 G_CALLBACK (focus_out_cb),
+                                 entry);
+}
+
+GtkWidget* eog_zoom_entry_new(EogScrollView *view, GMenu *menu)
+{
+       g_return_val_if_fail (EOG_IS_SCROLL_VIEW (view), NULL);
+       g_return_val_if_fail (G_IS_MENU (menu), NULL);
+
+       return g_object_new (EOG_TYPE_ZOOM_ENTRY,
+                            "scroll-view", view,
+                            "menu", menu,
+                            NULL);
+}
diff --git a/src/eog-zoom-entry.h b/src/eog-zoom-entry.h
new file mode 100644
index 0000000..a4ff716
--- /dev/null
+++ b/src/eog-zoom-entry.h
@@ -0,0 +1,41 @@
+/*
+ * eog-zoom-entry.h
+ * This file is part of eog
+ *
+ * Author: Felix Riemann <friemann gnome org>
+ *
+ * Copyright (C) 2017 GNOME Foundation
+ *
+ * Based on code (ev-zoom-action.c) by:
+ *      - Carlos Garcia Campos <carlosgc gnome org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef EOG_ZOOM_ENTRY_H
+#define EOG_ZOOM_ENTRY_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "eog-scroll-view.h"
+
+#define EOG_TYPE_ZOOM_ENTRY (eog_zoom_entry_get_type())
+
+G_DECLARE_FINAL_TYPE(EogZoomEntry, eog_zoom_entry, EOG, ZOOM_ENTRY, GtkBox);
+
+GtkWidget* eog_zoom_entry_new (EogScrollView *view, GMenu *menu);
+
+#endif /* EOG_ZOOM_ENTRY_H */
diff --git a/src/eog.gresource.xml b/src/eog.gresource.xml
index a819445..79f8071 100644
--- a/src/eog.gresource.xml
+++ b/src/eog.gresource.xml
@@ -8,6 +8,7 @@
     <file compressed="true" preprocess="xml-stripblanks">eog-preferences-dialog.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">fullscreen-toolbar.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">metadata-sidebar.ui</file>
+    <file compressed="true" preprocess="xml-stripblanks">eog-zoom-entry.ui</file>
     <file>pixmaps/thumbnail-frame.png</file>
     <file compressed="true" preprocess="xml-stripblanks">popup-menus.ui</file>
   </gresource>


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