[Xfce4-commits] <ristretto:master> Implement box-zoom (zoom to selection)

Stephan Arts noreply at xfce.org
Mon Aug 8 15:04:24 CEST 2011


Updating branch refs/heads/master
         to 0a18c04760f358f279a63b55de1ee46af69c0ccd (commit)
       from 1deeb369388f473bc651e43baf14985f480fbeae (commit)

commit 0a18c04760f358f279a63b55de1ee46af69c0ccd
Author: Stephan Arts <stephan at xfce.org>
Date:   Fri Aug 5 00:04:49 2011 +0200

    Implement box-zoom (zoom to selection)

 src/image_viewer.c |  157 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 155 insertions(+), 2 deletions(-)

diff --git a/src/image_viewer.c b/src/image_viewer.c
index 523ba7f..bb6b208 100644
--- a/src/image_viewer.c
+++ b/src/image_viewer.c
@@ -544,6 +544,13 @@ rstto_image_viewer_paint (GtkWidget *widget)
 
             if(viewer->priv->motion.state == RSTTO_IMAGE_VIEWER_MOTION_STATE_BOX_ZOOM)
             {
+                /*
+                 * The user can create a selection-box when dragging from four corners.
+                 * Check if the endpoint is before or after the starting-point,
+                 * calculate the offset and box-size accordingly.
+                 * 
+                 * Perform the calculations for the vertical movement.
+                 */
                 if (viewer->priv->motion.y < viewer->priv->motion.current_y)
                 {
                     box_y = viewer->priv->motion.y;
@@ -555,6 +562,9 @@ rstto_image_viewer_paint (GtkWidget *widget)
                     box_height = viewer->priv->motion.y - box_y;
                 }
 
+                /*
+                 * Above comment applies here aswell, for the horizontal movement.
+                 */
                 if (viewer->priv->motion.x < viewer->priv->motion.current_x)
                 {
                     box_x = viewer->priv->motion.x;
@@ -566,6 +576,9 @@ rstto_image_viewer_paint (GtkWidget *widget)
                     box_width = viewer->priv->motion.x - box_x;
                 }
 
+                /*
+                 * Finally, paint the selection-box.
+                 */
                 rstto_image_viewer_paint_selection (viewer, GDK_DRAWABLE(buffer), gc, box_width, box_height, box_x, box_y);
             }
         }
@@ -1452,12 +1465,27 @@ cb_rstto_image_viewer_scroll_event (RsttoImageViewer *viewer, GdkEventScroll *ev
 {
     gdouble tmp_x, tmp_y;
     gdouble scale;
+    GtkWidget *widget = GTK_WIDGET(viewer);
+
+    gint pixbuf_width;
+    gint pixbuf_height;
+    gint pixbuf_x_offset;
+    gint pixbuf_y_offset;
+
+
+    if (viewer->priv->dst_pixbuf)
+    {
+        pixbuf_width = gdk_pixbuf_get_width(viewer->priv->dst_pixbuf);
+        pixbuf_height = gdk_pixbuf_get_height(viewer->priv->dst_pixbuf);
+        pixbuf_x_offset = ((widget->allocation.width - pixbuf_width)/2);
+        pixbuf_y_offset = ((widget->allocation.height - pixbuf_height)/2);
+    }
 
     if ((event->state & (GDK_CONTROL_MASK)))
     {
             viewer->priv->auto_scale = FALSE;
-            tmp_x = (gtk_adjustment_get_value(viewer->hadjustment) + event->x) / viewer->priv->scale;
-            tmp_y = (gtk_adjustment_get_value(viewer->vadjustment) + event->y) / viewer->priv->scale;
+            tmp_x = (gtk_adjustment_get_value(viewer->hadjustment) + event->x) / viewer->priv->scale + pixbuf_x_offset;
+            tmp_y = (gtk_adjustment_get_value(viewer->vadjustment) + event->y) / viewer->priv->scale + pixbuf_y_offset;
 
             switch(event->direction)
             {
@@ -1654,6 +1682,49 @@ static void
 cb_rstto_image_viewer_button_release_event (RsttoImageViewer *viewer, GdkEventButton *event)
 {
     GtkWidget *widget = GTK_WIDGET(viewer);
+    gint box_x;
+    gint box_y;
+    gint box_width;
+    gint box_height;
+    gint pixbuf_width;
+    gint pixbuf_height;
+    gint pixbuf_x_offset;
+    gint pixbuf_y_offset;
+    gint width;
+    gint height;
+
+
+    pixbuf_width = gdk_pixbuf_get_width(viewer->priv->dst_pixbuf);
+    pixbuf_height = gdk_pixbuf_get_height(viewer->priv->dst_pixbuf);
+    pixbuf_x_offset = ((widget->allocation.width - pixbuf_width)/2);
+    pixbuf_y_offset = ((widget->allocation.height - pixbuf_height)/2);
+
+    width = gdk_pixbuf_get_width (viewer->priv->pixbuf);
+    height = gdk_pixbuf_get_height (viewer->priv->pixbuf);
+
+    if (viewer->priv->motion.y < viewer->priv->motion.current_y)
+    {
+        box_y = viewer->priv->motion.y;
+        box_height = viewer->priv->motion.current_y - box_y;
+    }
+    else
+    {
+        box_y = viewer->priv->motion.current_y;
+        box_height = viewer->priv->motion.y - box_y;
+    }
+
+    if (viewer->priv->motion.x < viewer->priv->motion.current_x)
+    {
+        box_x = viewer->priv->motion.x;
+        box_width = viewer->priv->motion.current_x - box_x;
+    }
+    else
+    {
+        box_x = viewer->priv->motion.current_x;
+        box_width = viewer->priv->motion.x - box_x;
+    }
+
+
     switch (event->button)
     {
         case 1:
@@ -1661,6 +1732,88 @@ cb_rstto_image_viewer_button_release_event (RsttoImageViewer *viewer, GdkEventBu
             switch (viewer->priv->motion.state)
             {
                 case RSTTO_IMAGE_VIEWER_MOTION_STATE_BOX_ZOOM:
+                    /*
+                     * Constrain the selection-box to the left
+                     * and top sides of the image.
+                     */
+                    if (box_x < pixbuf_x_offset)
+                    {
+                        box_width -= (pixbuf_x_offset - box_x);
+                        box_x = pixbuf_x_offset;
+                    }
+                    if (box_y < pixbuf_y_offset)
+                    {
+                        box_height -= (pixbuf_y_offset - box_y);
+                        box_y = pixbuf_y_offset;
+                    }
+
+                    /*
+                     * Constrain the selection-box to the right
+                     * and bottom sides of the image.
+                     */
+                    if ((box_x + box_width) > (pixbuf_x_offset+pixbuf_width))
+                    {
+                        box_width = (pixbuf_x_offset+pixbuf_width)-box_x;
+                    }
+                    if ((box_y + box_height) > (pixbuf_y_offset+pixbuf_height))
+                    {
+                        box_height = (pixbuf_y_offset+pixbuf_height)-box_y;
+                    }
+
+                    if ((box_width > 0) && (box_height > 0))
+                    {
+                        /*
+                         * Using BOX_ZOOM disables auto-scale (zoom-to-fit-widget)
+                         */
+                        viewer->priv->auto_scale = FALSE;
+                        
+                        /*
+                         * Calculate the center of the selection-box.
+                         */
+
+                        gdouble tmp_y = (gtk_adjustment_get_value(viewer->vadjustment) + (gdouble)box_y + ((gdouble)box_height/ 2)) / viewer->priv->scale + pixbuf_y_offset;
+
+                        gdouble tmp_x = (gtk_adjustment_get_value(viewer->hadjustment) + (gdouble)box_x + ((gdouble)box_width / 2)) / viewer->priv->scale + pixbuf_x_offset;
+
+                        /*
+                         * Calculate the new scale
+                         */
+                        gdouble scale;
+                        if ((gtk_adjustment_get_page_size(viewer->hadjustment) / box_width) > 
+                            (gtk_adjustment_get_page_size(viewer->vadjustment) / box_height))
+                        {
+                            scale = viewer->priv->scale * (gtk_adjustment_get_page_size(viewer->hadjustment) / box_width);
+                        }
+                        else
+                        {
+                            scale = viewer->priv->scale * (gtk_adjustment_get_page_size(viewer->vadjustment) / box_height);
+                        }
+
+                        /*
+                         * Prevent the widget from zooming in beyond the MAX_SCALE.
+                         */
+                        if (scale > RSTTO_MAX_SCALE)
+                        {
+                            scale = RSTTO_MAX_SCALE;
+                        }
+
+                        viewer->priv->scale = scale;
+
+                        
+                        g_object_freeze_notify(G_OBJECT(viewer->hadjustment));
+                        gtk_adjustment_set_upper (viewer->hadjustment, (gdouble)width*(viewer->priv->scale/viewer->priv->image_scale));
+                        gtk_adjustment_set_value (viewer->hadjustment, (tmp_x * scale - ((gdouble)gtk_adjustment_get_page_size(viewer->hadjustment)/2)));
+                        g_object_thaw_notify(G_OBJECT(viewer->hadjustment));
+
+                        g_object_freeze_notify(G_OBJECT(viewer->vadjustment));
+                        gtk_adjustment_set_upper (viewer->vadjustment, (gdouble)height*(viewer->priv->scale/viewer->priv->image_scale));
+                        gtk_adjustment_set_value (viewer->vadjustment, (tmp_y * scale - ((gdouble)gtk_adjustment_get_page_size(viewer->vadjustment)/2)));
+                        g_object_thaw_notify(G_OBJECT(viewer->vadjustment));
+
+                        gtk_adjustment_changed(viewer->hadjustment);
+                        gtk_adjustment_changed(viewer->vadjustment);
+
+                    }
                     break;
                 default:
                     break;


More information about the Xfce4-commits mailing list