From c0dbd4db66a540890f7c2bd2789b85218277cfa6 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Sat, 6 May 2000 07:07:03 +0000 Subject: [PATCH] New "zoom_fit" class to ask the parent to zoom to fit. 2000-05-05 Federico Mena Quintero * image-view.c: New "zoom_fit" class to ask the parent to zoom to fit. * ui-image.c (zoom_fit_cb): New handler for the "zoom_fit" signal of the image view. * window.c (set_mode): Give the focus to the image view widget. * full-screen.c (full_screen_key_press): Doh, call the parent class handler. (full_screen_show): Give the focus to the image view widget. * image-view.c (image_view_key_press): New handler for key presses. * commands.c (set_window_zoom): New function. Now we use this in all other command callbacks. (cmd_cb_zoom_fit): Use ui_image_zoom_fit(). (cmd_cb_full_screen): Use the FullScreen widget directly. * full-screen.c (full_screen_set_image): Get the image view and operate on it. * window.c (window_open_image): Likewise. Removed zooming functions. * ui-image.c (ui_image_get_image_view): New function. Removed image and zooming functions. (ui_image_zoom_fit): Set the zoom directly on the image view. --- libeog/image-view.c | 123 ++++++++++++++++++++++++++++++++++- libeog/image-view.h | 3 + libeog/ui-image.c | 90 ++++++-------------------- libeog/ui-image.h | 5 +- src/ChangeLog | 32 +++++++++ src/commands.c | 77 +++++++++++++++------- src/full-screen.c | 17 ++++- src/image-view.c | 123 ++++++++++++++++++++++++++++++++++- src/image-view.h | 3 + src/ui-image.c | 90 ++++++-------------------- src/ui-image.h | 5 +- src/window.c | 154 ++++---------------------------------------- src/window.h | 9 +-- 13 files changed, 409 insertions(+), 322 deletions(-) diff --git a/libeog/image-view.c b/libeog/image-view.c index 06f928b2..e7f96e3c 100644 --- a/libeog/image-view.c +++ b/libeog/image-view.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "cursors.h" #include "image-view.h" @@ -81,6 +82,12 @@ typedef struct { +/* Signal IDs */ +enum { + ZOOM_FIT, + LAST_SIGNAL +}; + static void image_view_class_init (ImageViewClass *class); static void image_view_init (ImageView *view); static void image_view_destroy (GtkObject *object); @@ -96,12 +103,15 @@ static gint image_view_button_press (GtkWidget *widget, GdkEventButton *event); static gint image_view_button_release (GtkWidget *widget, GdkEventButton *event); static gint image_view_motion (GtkWidget *widget, GdkEventMotion *event); static gint image_view_expose (GtkWidget *widget, GdkEventExpose *event); +static gint image_view_key_press (GtkWidget *widget, GdkEventKey *event); static void image_view_set_scroll_adjustments (GtkWidget *widget, GtkAdjustment *hadj, GtkAdjustment *vadj); static GtkWidgetClass *parent_class; +static guint image_view_signals[LAST_SIGNAL]; + /** @@ -148,6 +158,14 @@ image_view_class_init (ImageViewClass *class) parent_class = gtk_type_class (GTK_TYPE_WIDGET); + image_view_signals[ZOOM_FIT] = + gtk_signal_new ("zoom_fit", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (ImageViewClass, zoom_fit), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + object_class->destroy = image_view_destroy; object_class->finalize = image_view_finalize; @@ -162,6 +180,8 @@ image_view_class_init (ImageViewClass *class) GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT); + gtk_object_class_add_signals (object_class, image_view_signals, LAST_SIGNAL); + widget_class->unmap = image_view_unmap; widget_class->realize = image_view_realize; widget_class->unrealize = image_view_unrealize; @@ -172,6 +192,7 @@ image_view_class_init (ImageViewClass *class) widget_class->button_release_event = image_view_button_release; widget_class->motion_notify_event = image_view_motion; widget_class->expose_event = image_view_expose; + widget_class->key_press_event = image_view_key_press; } /* Object initialization function for the image view */ @@ -183,6 +204,8 @@ image_view_init (ImageView *view) priv = g_new0 (ImageViewPrivate, 1); view->priv = priv; + GTK_WIDGET_SET_FLAGS (view, GTK_CAN_FOCUS); + priv->zoom = 1.0; GTK_WIDGET_UNSET_FLAGS (view, GTK_NO_WINDOW); @@ -707,7 +730,7 @@ image_view_realize (GtkWidget *widget) attr.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK - | GDK_BUTTON_RELEASE_MASK); + | GDK_KEY_PRESS_MASK); attr_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; @@ -909,6 +932,9 @@ image_view_button_press (GtkWidget *widget, GdkEventButton *event) view = IMAGE_VIEW (widget); priv = view->priv; + if (!GTK_WIDGET_HAS_FOCUS (widget)) + gtk_widget_grab_focus (widget); + if (priv->dragging || event->button != 1) return FALSE; @@ -1025,6 +1051,101 @@ image_view_expose (GtkWidget *widget, GdkEventExpose *event) return TRUE; } +/* Key press handler for the image view */ +static gint +image_view_key_press (GtkWidget *widget, GdkEventKey *event) +{ + ImageView *view; + ImageViewPrivate *priv; + gboolean do_zoom; + double zoom; + gboolean do_scroll; + int xofs, yofs; + + view = IMAGE_VIEW (widget); + priv = view->priv; + + do_zoom = FALSE; + do_scroll = FALSE; + + switch (event->keyval) { + case GDK_Up: + do_scroll = TRUE; + xofs = 0; + yofs = -SCROLL_STEP_SIZE; + break; + + case GDK_Down: + do_scroll = TRUE; + xofs = 0; + yofs = SCROLL_STEP_SIZE; + break; + + case GDK_Left: + do_scroll = TRUE; + xofs = -SCROLL_STEP_SIZE; + yofs = 0; + break; + + case GDK_Right: + do_scroll = TRUE; + xofs = SCROLL_STEP_SIZE; + yofs = 0; + break; + + case GDK_equal: + case GDK_KP_Add: + do_zoom = TRUE; + zoom = priv->zoom * 1.05; + break; + + case GDK_minus: + case GDK_KP_Subtract: + do_zoom = TRUE; + zoom = priv->zoom / 1.05; + break; + + case GDK_1: + do_zoom = TRUE; + zoom = 1.0; + break; + + case GDK_F: + case GDK_f: + gtk_signal_emit (GTK_OBJECT (view), image_view_signals[ZOOM_FIT]); + break; + + default: + return FALSE; + } + + if (do_zoom) + image_view_set_zoom (view, zoom); + + if (do_scroll) { + int x, y; + + x = CLAMP (priv->xofs + xofs, 0, priv->hadj->upper - priv->hadj->page_size); + y = CLAMP (priv->yofs + yofs, 0, priv->vadj->upper - priv->vadj->page_size); + + scroll_to (view, x, y); + + gtk_signal_handler_block_by_data (GTK_OBJECT (priv->hadj), view); + gtk_signal_handler_block_by_data (GTK_OBJECT (priv->vadj), view); + + priv->hadj->value = x; + priv->vadj->value = y; + + gtk_signal_emit_by_name (GTK_OBJECT (priv->hadj), "value_changed"); + gtk_signal_emit_by_name (GTK_OBJECT (priv->vadj), "value_changed"); + + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->hadj), view); + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->vadj), view); + } + + return TRUE; +} + /* Callback used when an adjustment is changed */ static void adjustment_changed_cb (GtkAdjustment *adj, gpointer data) diff --git a/libeog/image-view.h b/libeog/image-view.h index dec4e4a8..b387b66b 100644 --- a/libeog/image-view.h +++ b/libeog/image-view.h @@ -49,6 +49,9 @@ struct _ImageView { struct _ImageViewClass { GtkWidgetClass parent_class; + /* Notification signals */ + void (* zoom_fit) (ImageView *view); + /* GTK+ scrolling interface */ void (* set_scroll_adjustments) (GtkWidget *widget, GtkAdjustment *hadj, diff --git a/libeog/ui-image.c b/libeog/ui-image.c index e2f4a6d0..229f2291 100644 --- a/libeog/ui-image.c +++ b/libeog/ui-image.c @@ -147,6 +147,16 @@ ui_image_new (void) return ui_image_construct (ui); } +/* Callback for the zoom_fit signal of the image view */ +static void +zoom_fit_cb (ImageView *view, gpointer data) +{ + UIImage *ui; + + ui = UI_IMAGE (data); + ui_image_zoom_fit (ui); +} + /** * ui_image_construct: * @ui: An image view scroller. @@ -167,6 +177,8 @@ ui_image_construct (UIImage *ui) priv = ui->priv; priv->view = image_view_new (); + gtk_signal_connect (GTK_OBJECT (priv->view), "zoom_fit", + GTK_SIGNAL_FUNC (zoom_fit_cb), ui); gtk_container_add (GTK_CONTAINER (ui), priv->view); gtk_widget_show (priv->view); @@ -176,35 +188,15 @@ ui_image_construct (UIImage *ui) /** - * ui_image_set_image: - * @ui: An image view scroller. - * @image: An image structure, or NULL if none. - * - * Sets the image to be displayed in an image view scroller. - **/ -void -ui_image_set_image (UIImage *ui, Image *image) -{ - UIImagePrivate *priv; - - g_return_if_fail (ui != NULL); - g_return_if_fail (IS_UI_IMAGE (ui)); - - priv = ui->priv; - - image_view_set_image (IMAGE_VIEW (priv->view), image); -} - -/** - * ui_image_get_image: + * ui_image_get_image_view: * @ui: An image view scroller. * - * Queries the image that an image view scroller is displaying. + * Queries the image view widget that is inside an image view scroller. * - * Return value: An image, or NULL if no image is being displayed. + * Return value: An image view widget. **/ -Image * -ui_image_get_image (UIImage *ui) +GtkWidget * +ui_image_get_image_view (UIImage *ui) { UIImagePrivate *priv; @@ -212,49 +204,7 @@ ui_image_get_image (UIImage *ui) g_return_val_if_fail (IS_UI_IMAGE (ui), NULL); priv = ui->priv; - return image_view_get_image (IMAGE_VIEW (priv->view)); -} - -/** - * ui_image_set_zoom: - * @ui: An image view scroller. - * @zoom: Desired zoom factor. - * - * Sets the zoom factor of an image view scroller. - **/ -void -ui_image_set_zoom (UIImage *ui, double zoom) -{ - UIImagePrivate *priv; - - g_return_if_fail (ui != NULL); - g_return_if_fail (IS_UI_IMAGE (ui)); - g_return_if_fail (zoom > 0.0); - - priv = ui->priv; - - image_view_set_zoom (IMAGE_VIEW (priv->view), zoom); -} - -/** - * ui_image_get_zoom: - * @ui: An image view scroller. - * - * Gets the current zoom factor of an image view scroller. - * - * Return value: Current zoom factor. - **/ -double -ui_image_get_zoom (UIImage *ui) -{ - UIImagePrivate *priv; - - g_return_val_if_fail (ui != NULL, -1.0); - g_return_val_if_fail (IS_UI_IMAGE (ui), -1.0); - - priv = ui->priv; - - return image_view_get_zoom (IMAGE_VIEW (priv->view)); + return priv->view; } /** @@ -279,7 +229,7 @@ ui_image_zoom_fit (UIImage *ui) image = image_view_get_image (IMAGE_VIEW (priv->view)); if (!image) { - ui_image_set_zoom (ui, 1.0); + image_view_set_zoom (IMAGE_VIEW (priv->view), 1.0); return; } @@ -295,5 +245,5 @@ ui_image_zoom_fit (UIImage *ui) iw = ih = 0; zoom = zoom_fit_scale (w - 2 * xthick, h - 2 * ythick, iw, ih, TRUE); - ui_image_set_zoom (ui, zoom); + image_view_set_zoom (IMAGE_VIEW (priv->view), zoom); } diff --git a/libeog/ui-image.h b/libeog/ui-image.h index f8a34ba4..29b9c0b5 100644 --- a/libeog/ui-image.h +++ b/libeog/ui-image.h @@ -57,11 +57,8 @@ GtkType ui_image_get_type (void); GtkWidget *ui_image_new (void); GtkWidget *ui_image_construct (UIImage *ui); -void ui_image_set_image (UIImage *ui, Image *image); -Image *ui_image_get_image (UIImage *ui); +GtkWidget *ui_image_get_image_view (UIImage *ui); -void ui_image_set_zoom (UIImage *ui, double zoom); -double ui_image_get_zoom (UIImage *ui); void ui_image_zoom_fit (UIImage *ui); diff --git a/src/ChangeLog b/src/ChangeLog index 4e31a659..22bd2692 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,35 @@ +2000-05-05 Federico Mena Quintero + + * image-view.c: New "zoom_fit" class to ask the parent to zoom to + fit. + + * ui-image.c (zoom_fit_cb): New handler for the "zoom_fit" signal + of the image view. + + * window.c (set_mode): Give the focus to the image view widget. + + * full-screen.c (full_screen_key_press): Doh, call the parent + class handler. + (full_screen_show): Give the focus to the image view widget. + + * image-view.c (image_view_key_press): New handler for key + presses. + + * commands.c (set_window_zoom): New function. Now we use this in + all other command callbacks. + (cmd_cb_zoom_fit): Use ui_image_zoom_fit(). + (cmd_cb_full_screen): Use the FullScreen widget directly. + + * full-screen.c (full_screen_set_image): Get the image view and + operate on it. + + * window.c (window_open_image): Likewise. + Removed zooming functions. + + * ui-image.c (ui_image_get_image_view): New function. + Removed image and zooming functions. + (ui_image_zoom_fit): Set the zoom directly on the image view. + 2000-04-27 Darin Adler * window.c (window_full_screen): diff --git a/src/commands.c b/src/commands.c index a516a3cb..f2d97a2b 100644 --- a/src/commands.c +++ b/src/commands.c @@ -21,10 +21,29 @@ #include #include "commands.h" +#include "full-screen.h" +#include "image-view.h" +#include "ui-image.h" #include "window.h" +/* Sets the zoom factor of a window's image view */ +static void +set_window_zoom (Window *window, double zoom, gboolean mult) +{ + UIImage *ui; + ImageView *view; + + ui = UI_IMAGE (window_get_ui_image (window)); + view = IMAGE_VIEW (ui_image_get_image_view (ui)); + + if (mult) + zoom *= image_view_get_zoom (view); + + image_view_set_zoom (view, zoom); +} + void cmd_cb_image_open (GtkWidget *widget, gpointer data) { @@ -40,31 +59,43 @@ cmd_cb_window_close (GtkWidget *widget, gpointer data) void cmd_cb_zoom_in (GtkWidget *widget, gpointer data) { - window_zoom_in (WINDOW (data)); + set_window_zoom (WINDOW (data), 1.05, TRUE); } void cmd_cb_zoom_out (GtkWidget *widget, gpointer data) { - window_zoom_out (WINDOW (data)); + set_window_zoom (WINDOW (data), 1.0 / 1.05, TRUE); } void cmd_cb_zoom_1 (GtkWidget *widget, gpointer data) { - window_zoom_1 (WINDOW (data)); + set_window_zoom (WINDOW (data), 1.0, FALSE); } void cmd_cb_zoom_fit (GtkWidget *widget, gpointer data) { - window_zoom_fit (WINDOW (data)); + UIImage *ui; + + ui = UI_IMAGE (window_get_ui_image (WINDOW (data))); + ui_image_zoom_fit (ui); } void cmd_cb_full_screen (GtkWidget *widget, gpointer data) { - window_full_screen (WINDOW (data)); + UIImage *ui; + ImageView *view; + GtkWidget *fs; + + ui = UI_IMAGE (window_get_ui_image (WINDOW (data))); + view = IMAGE_VIEW (ui_image_get_image_view (ui)); + + fs = full_screen_new (); + full_screen_set_image (FULL_SCREEN (fs), image_view_get_image (view)); + gtk_widget_show (fs); } @@ -72,55 +103,55 @@ cmd_cb_full_screen (GtkWidget *widget, gpointer data) void cmd_cb_zoom_2_1 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 2.0); + set_window_zoom (WINDOW (data), 2.0, FALSE); } void cmd_cb_zoom_3_1 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 3.0); + set_window_zoom (WINDOW (data), 3.0, FALSE); } void cmd_cb_zoom_4_1 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 4.0); + set_window_zoom (WINDOW (data), 4.0, FALSE); } void cmd_cb_zoom_5_1 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 5.0); + set_window_zoom (WINDOW (data), 5.0, FALSE); } void cmd_cb_zoom_6_1 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 6.0); + set_window_zoom (WINDOW (data), 6.0, FALSE); } void cmd_cb_zoom_7_1 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 7.0); + set_window_zoom (WINDOW (data), 7.0, FALSE); } void cmd_cb_zoom_8_1 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 8.0); + set_window_zoom (WINDOW (data), 8.0, FALSE); } void cmd_cb_zoom_9_1 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 9.0); + set_window_zoom (WINDOW (data), 9.0, FALSE); } void cmd_cb_zoom_10_1 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 10.0); + set_window_zoom (WINDOW (data), 10.0, FALSE); } @@ -128,53 +159,53 @@ cmd_cb_zoom_10_1 (GtkWidget *widget, gpointer data) void cmd_cb_zoom_1_2 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 1.0 / 2.0); + set_window_zoom (WINDOW (data), 1.0 / 2.0, FALSE); } void cmd_cb_zoom_1_3 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 1.0 / 3.0); + set_window_zoom (WINDOW (data), 1.0 / 3.0, FALSE); } void cmd_cb_zoom_1_4 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 1.0 / 4.0); + set_window_zoom (WINDOW (data), 1.0 / 4.0, FALSE); } void cmd_cb_zoom_1_5 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 1.0 / 5.0); + set_window_zoom (WINDOW (data), 1.0 / 5.0, FALSE); } void cmd_cb_zoom_1_6 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 1.0 / 6.0); + set_window_zoom (WINDOW (data), 1.0 / 6.0, FALSE); } void cmd_cb_zoom_1_7 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 1.0 / 7.0); + set_window_zoom (WINDOW (data), 1.0 / 7.0, FALSE); } void cmd_cb_zoom_1_8 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 1.0 / 8.0); + set_window_zoom (WINDOW (data), 1.0 / 8.0, FALSE); } void cmd_cb_zoom_1_9 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 1.0 / 9.0); + set_window_zoom (WINDOW (data), 1.0 / 9.0, FALSE); } void cmd_cb_zoom_1_10 (GtkWidget *widget, gpointer data) { - window_set_zoom (WINDOW (data), 1.0 / 10.0); + set_window_zoom (WINDOW (data), 1.0 / 10.0, FALSE); } diff --git a/src/full-screen.c b/src/full-screen.c index b3250ac0..a311bc28 100644 --- a/src/full-screen.c +++ b/src/full-screen.c @@ -23,6 +23,7 @@ #include #include #include "full-screen.h" +#include "image-view.h" #include "ui-image.h" @@ -159,6 +160,8 @@ full_screen_show (GtkWidget *widget) priv->have_grab = gdk_keyboard_grab (widget->window, TRUE, GDK_CURRENT_TIME) == 0; gtk_grab_add (widget); + + gtk_widget_grab_focus (ui_image_get_image_view (UI_IMAGE (priv->ui))); } /* Hide handler for the full screen view */ @@ -186,6 +189,16 @@ full_screen_hide (GtkWidget *widget) static gint full_screen_key_press (GtkWidget *widget, GdkEventKey *event) { + gint result; + + result = FALSE; + + if (GTK_WIDGET_CLASS (parent_class)->key_press_event) + result = (* GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget, event); + + if (result) + return result; + if (event->keyval == GDK_Escape) { gtk_widget_hide (widget); return TRUE; @@ -221,11 +234,13 @@ void full_screen_set_image (FullScreen *fs, Image *image) { FullScreenPrivate *priv; + GtkWidget *view; g_return_if_fail (fs != NULL); g_return_if_fail (IS_FULL_SCREEN (fs)); priv = fs->priv; - ui_image_set_image (UI_IMAGE (priv->ui), image); + view = ui_image_get_image_view (UI_IMAGE (priv->ui)); + image_view_set_image (IMAGE_VIEW (view), image); } diff --git a/src/image-view.c b/src/image-view.c index 06f928b2..e7f96e3c 100644 --- a/src/image-view.c +++ b/src/image-view.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "cursors.h" #include "image-view.h" @@ -81,6 +82,12 @@ typedef struct { +/* Signal IDs */ +enum { + ZOOM_FIT, + LAST_SIGNAL +}; + static void image_view_class_init (ImageViewClass *class); static void image_view_init (ImageView *view); static void image_view_destroy (GtkObject *object); @@ -96,12 +103,15 @@ static gint image_view_button_press (GtkWidget *widget, GdkEventButton *event); static gint image_view_button_release (GtkWidget *widget, GdkEventButton *event); static gint image_view_motion (GtkWidget *widget, GdkEventMotion *event); static gint image_view_expose (GtkWidget *widget, GdkEventExpose *event); +static gint image_view_key_press (GtkWidget *widget, GdkEventKey *event); static void image_view_set_scroll_adjustments (GtkWidget *widget, GtkAdjustment *hadj, GtkAdjustment *vadj); static GtkWidgetClass *parent_class; +static guint image_view_signals[LAST_SIGNAL]; + /** @@ -148,6 +158,14 @@ image_view_class_init (ImageViewClass *class) parent_class = gtk_type_class (GTK_TYPE_WIDGET); + image_view_signals[ZOOM_FIT] = + gtk_signal_new ("zoom_fit", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (ImageViewClass, zoom_fit), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + object_class->destroy = image_view_destroy; object_class->finalize = image_view_finalize; @@ -162,6 +180,8 @@ image_view_class_init (ImageViewClass *class) GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT); + gtk_object_class_add_signals (object_class, image_view_signals, LAST_SIGNAL); + widget_class->unmap = image_view_unmap; widget_class->realize = image_view_realize; widget_class->unrealize = image_view_unrealize; @@ -172,6 +192,7 @@ image_view_class_init (ImageViewClass *class) widget_class->button_release_event = image_view_button_release; widget_class->motion_notify_event = image_view_motion; widget_class->expose_event = image_view_expose; + widget_class->key_press_event = image_view_key_press; } /* Object initialization function for the image view */ @@ -183,6 +204,8 @@ image_view_init (ImageView *view) priv = g_new0 (ImageViewPrivate, 1); view->priv = priv; + GTK_WIDGET_SET_FLAGS (view, GTK_CAN_FOCUS); + priv->zoom = 1.0; GTK_WIDGET_UNSET_FLAGS (view, GTK_NO_WINDOW); @@ -707,7 +730,7 @@ image_view_realize (GtkWidget *widget) attr.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK - | GDK_BUTTON_RELEASE_MASK); + | GDK_KEY_PRESS_MASK); attr_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; @@ -909,6 +932,9 @@ image_view_button_press (GtkWidget *widget, GdkEventButton *event) view = IMAGE_VIEW (widget); priv = view->priv; + if (!GTK_WIDGET_HAS_FOCUS (widget)) + gtk_widget_grab_focus (widget); + if (priv->dragging || event->button != 1) return FALSE; @@ -1025,6 +1051,101 @@ image_view_expose (GtkWidget *widget, GdkEventExpose *event) return TRUE; } +/* Key press handler for the image view */ +static gint +image_view_key_press (GtkWidget *widget, GdkEventKey *event) +{ + ImageView *view; + ImageViewPrivate *priv; + gboolean do_zoom; + double zoom; + gboolean do_scroll; + int xofs, yofs; + + view = IMAGE_VIEW (widget); + priv = view->priv; + + do_zoom = FALSE; + do_scroll = FALSE; + + switch (event->keyval) { + case GDK_Up: + do_scroll = TRUE; + xofs = 0; + yofs = -SCROLL_STEP_SIZE; + break; + + case GDK_Down: + do_scroll = TRUE; + xofs = 0; + yofs = SCROLL_STEP_SIZE; + break; + + case GDK_Left: + do_scroll = TRUE; + xofs = -SCROLL_STEP_SIZE; + yofs = 0; + break; + + case GDK_Right: + do_scroll = TRUE; + xofs = SCROLL_STEP_SIZE; + yofs = 0; + break; + + case GDK_equal: + case GDK_KP_Add: + do_zoom = TRUE; + zoom = priv->zoom * 1.05; + break; + + case GDK_minus: + case GDK_KP_Subtract: + do_zoom = TRUE; + zoom = priv->zoom / 1.05; + break; + + case GDK_1: + do_zoom = TRUE; + zoom = 1.0; + break; + + case GDK_F: + case GDK_f: + gtk_signal_emit (GTK_OBJECT (view), image_view_signals[ZOOM_FIT]); + break; + + default: + return FALSE; + } + + if (do_zoom) + image_view_set_zoom (view, zoom); + + if (do_scroll) { + int x, y; + + x = CLAMP (priv->xofs + xofs, 0, priv->hadj->upper - priv->hadj->page_size); + y = CLAMP (priv->yofs + yofs, 0, priv->vadj->upper - priv->vadj->page_size); + + scroll_to (view, x, y); + + gtk_signal_handler_block_by_data (GTK_OBJECT (priv->hadj), view); + gtk_signal_handler_block_by_data (GTK_OBJECT (priv->vadj), view); + + priv->hadj->value = x; + priv->vadj->value = y; + + gtk_signal_emit_by_name (GTK_OBJECT (priv->hadj), "value_changed"); + gtk_signal_emit_by_name (GTK_OBJECT (priv->vadj), "value_changed"); + + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->hadj), view); + gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->vadj), view); + } + + return TRUE; +} + /* Callback used when an adjustment is changed */ static void adjustment_changed_cb (GtkAdjustment *adj, gpointer data) diff --git a/src/image-view.h b/src/image-view.h index dec4e4a8..b387b66b 100644 --- a/src/image-view.h +++ b/src/image-view.h @@ -49,6 +49,9 @@ struct _ImageView { struct _ImageViewClass { GtkWidgetClass parent_class; + /* Notification signals */ + void (* zoom_fit) (ImageView *view); + /* GTK+ scrolling interface */ void (* set_scroll_adjustments) (GtkWidget *widget, GtkAdjustment *hadj, diff --git a/src/ui-image.c b/src/ui-image.c index e2f4a6d0..229f2291 100644 --- a/src/ui-image.c +++ b/src/ui-image.c @@ -147,6 +147,16 @@ ui_image_new (void) return ui_image_construct (ui); } +/* Callback for the zoom_fit signal of the image view */ +static void +zoom_fit_cb (ImageView *view, gpointer data) +{ + UIImage *ui; + + ui = UI_IMAGE (data); + ui_image_zoom_fit (ui); +} + /** * ui_image_construct: * @ui: An image view scroller. @@ -167,6 +177,8 @@ ui_image_construct (UIImage *ui) priv = ui->priv; priv->view = image_view_new (); + gtk_signal_connect (GTK_OBJECT (priv->view), "zoom_fit", + GTK_SIGNAL_FUNC (zoom_fit_cb), ui); gtk_container_add (GTK_CONTAINER (ui), priv->view); gtk_widget_show (priv->view); @@ -176,35 +188,15 @@ ui_image_construct (UIImage *ui) /** - * ui_image_set_image: - * @ui: An image view scroller. - * @image: An image structure, or NULL if none. - * - * Sets the image to be displayed in an image view scroller. - **/ -void -ui_image_set_image (UIImage *ui, Image *image) -{ - UIImagePrivate *priv; - - g_return_if_fail (ui != NULL); - g_return_if_fail (IS_UI_IMAGE (ui)); - - priv = ui->priv; - - image_view_set_image (IMAGE_VIEW (priv->view), image); -} - -/** - * ui_image_get_image: + * ui_image_get_image_view: * @ui: An image view scroller. * - * Queries the image that an image view scroller is displaying. + * Queries the image view widget that is inside an image view scroller. * - * Return value: An image, or NULL if no image is being displayed. + * Return value: An image view widget. **/ -Image * -ui_image_get_image (UIImage *ui) +GtkWidget * +ui_image_get_image_view (UIImage *ui) { UIImagePrivate *priv; @@ -212,49 +204,7 @@ ui_image_get_image (UIImage *ui) g_return_val_if_fail (IS_UI_IMAGE (ui), NULL); priv = ui->priv; - return image_view_get_image (IMAGE_VIEW (priv->view)); -} - -/** - * ui_image_set_zoom: - * @ui: An image view scroller. - * @zoom: Desired zoom factor. - * - * Sets the zoom factor of an image view scroller. - **/ -void -ui_image_set_zoom (UIImage *ui, double zoom) -{ - UIImagePrivate *priv; - - g_return_if_fail (ui != NULL); - g_return_if_fail (IS_UI_IMAGE (ui)); - g_return_if_fail (zoom > 0.0); - - priv = ui->priv; - - image_view_set_zoom (IMAGE_VIEW (priv->view), zoom); -} - -/** - * ui_image_get_zoom: - * @ui: An image view scroller. - * - * Gets the current zoom factor of an image view scroller. - * - * Return value: Current zoom factor. - **/ -double -ui_image_get_zoom (UIImage *ui) -{ - UIImagePrivate *priv; - - g_return_val_if_fail (ui != NULL, -1.0); - g_return_val_if_fail (IS_UI_IMAGE (ui), -1.0); - - priv = ui->priv; - - return image_view_get_zoom (IMAGE_VIEW (priv->view)); + return priv->view; } /** @@ -279,7 +229,7 @@ ui_image_zoom_fit (UIImage *ui) image = image_view_get_image (IMAGE_VIEW (priv->view)); if (!image) { - ui_image_set_zoom (ui, 1.0); + image_view_set_zoom (IMAGE_VIEW (priv->view), 1.0); return; } @@ -295,5 +245,5 @@ ui_image_zoom_fit (UIImage *ui) iw = ih = 0; zoom = zoom_fit_scale (w - 2 * xthick, h - 2 * ythick, iw, ih, TRUE); - ui_image_set_zoom (ui, zoom); + image_view_set_zoom (IMAGE_VIEW (priv->view), zoom); } diff --git a/src/ui-image.h b/src/ui-image.h index f8a34ba4..29b9c0b5 100644 --- a/src/ui-image.h +++ b/src/ui-image.h @@ -57,11 +57,8 @@ GtkType ui_image_get_type (void); GtkWidget *ui_image_new (void); GtkWidget *ui_image_construct (UIImage *ui); -void ui_image_set_image (UIImage *ui, Image *image); -Image *ui_image_get_image (UIImage *ui); +GtkWidget *ui_image_get_image_view (UIImage *ui); -void ui_image_set_zoom (UIImage *ui, double zoom); -double ui_image_get_zoom (UIImage *ui); void ui_image_zoom_fit (UIImage *ui); diff --git a/src/window.c b/src/window.c index baace51e..1e3da42c 100644 --- a/src/window.c +++ b/src/window.c @@ -23,6 +23,7 @@ #include #include "commands.h" #include "full-screen.h" +#include "image-view.h" #include "tb-image.h" #include "ui-image.h" #include "util.h" @@ -232,6 +233,7 @@ set_mode (Window *window, WindowMode mode) priv->content = ui_image_new (); gnome_app_set_contents (GNOME_APP (window), priv->content); gtk_widget_show (priv->content); + gtk_widget_grab_focus (ui_image_get_image_view (UI_IMAGE (priv->content))); break; case WINDOW_MODE_COLLECTION: @@ -711,6 +713,7 @@ window_open_image (Window *window, const char *filename) gboolean retval; char *fname; gboolean free_fname; + GtkWidget *view; g_return_val_if_fail (window != NULL, FALSE); g_return_val_if_fail (IS_WINDOW (window), FALSE); @@ -723,7 +726,8 @@ window_open_image (Window *window, const char *filename) image = image_new (); retval = image_load (image, filename); - ui_image_set_image (UI_IMAGE (priv->content), image); + view = ui_image_get_image_view (UI_IMAGE (priv->content)); + image_view_set_image (IMAGE_VIEW (view), image); free_fname = FALSE; @@ -748,152 +752,22 @@ window_open_image (Window *window, const char *filename) return retval; } - - /** - * window_set_zoom: - * @window: An image window. - * @zoom: Desired zoom factor. + * window_get_ui_image: + * @window: A window. * - * Sets the zoom factor for an image window. - **/ -void -window_set_zoom (Window *window, double zoom) -{ - WindowPrivate *priv; - UIImage *ui; - - g_return_if_fail (window != NULL); - g_return_if_fail (IS_WINDOW (window)); - - priv = window->priv; - g_return_if_fail (priv->mode == WINDOW_MODE_IMAGE); - - g_assert (priv->content != NULL && IS_UI_IMAGE (priv->content)); - ui = UI_IMAGE (priv->content); - - ui_image_set_zoom (ui, zoom); -} - -/** - * window_zoom_in: - * @window: An image window. - * - * Zooms in an image window. - **/ -void -window_zoom_in (Window *window) -{ - WindowPrivate *priv; - UIImage *ui; - - g_return_if_fail (window != NULL); - g_return_if_fail (IS_WINDOW (window)); - - priv = window->priv; - g_return_if_fail (priv->mode == WINDOW_MODE_IMAGE); - - g_assert (priv->content != NULL && IS_UI_IMAGE (priv->content)); - ui = UI_IMAGE (priv->content); - - ui_image_set_zoom (ui, ui_image_get_zoom (ui) * 1.05); -} - -/** - * window_zoom_out: - * @window: An image window. - * - * Zooms out an image window. - **/ -void -window_zoom_out (Window *window) -{ - WindowPrivate *priv; - UIImage *ui; - - g_return_if_fail (window != NULL); - g_return_if_fail (IS_WINDOW (window)); - - priv = window->priv; - g_return_if_fail (priv->mode == WINDOW_MODE_IMAGE); - - g_assert (priv->content != NULL && IS_UI_IMAGE (priv->content)); - ui = UI_IMAGE (priv->content); - - ui_image_set_zoom (ui, ui_image_get_zoom (ui) / 1.05); -} - -/** - * window_zoom_1: - * @window: An image window. + * Queries the image view scroller inside a window. * - * Zooms the image to 1:1 scale. + * Return value: An image view scroller. **/ -void -window_zoom_1 (Window *window) +GtkWidget * +window_get_ui_image (Window *window) { WindowPrivate *priv; - UIImage *ui; - g_return_if_fail (window != NULL); - g_return_if_fail (IS_WINDOW (window)); + g_return_val_if_fail (window != NULL, NULL); + g_return_val_if_fail (IS_WINDOW (window), NULL); priv = window->priv; - g_return_if_fail (priv->mode == WINDOW_MODE_IMAGE); - - g_assert (priv->content != NULL && IS_UI_IMAGE (priv->content)); - ui = UI_IMAGE (priv->content); - - ui_image_set_zoom (ui, 1.0); -} - -/** - * window_zoom_fit: - * @window: An image window. - * - * Zooms an image to fit the window size. - **/ -void -window_zoom_fit (Window *window) -{ - WindowPrivate *priv; - UIImage *ui; - - g_return_if_fail (window != NULL); - g_return_if_fail (IS_WINDOW (window)); - - priv = window->priv; - g_return_if_fail (priv->mode == WINDOW_MODE_IMAGE); - - g_assert (priv->content != NULL && IS_UI_IMAGE (priv->content)); - ui = UI_IMAGE (priv->content); - - ui_image_zoom_fit (ui); -} - -/** - * window_full_screen: - * @window: An image window. - * - * Launches a full screen viewer for an image window. - **/ -void -window_full_screen (Window *window) -{ - WindowPrivate *priv; - UIImage *ui; - GtkWidget *fs; - - g_return_if_fail (window != NULL); - g_return_if_fail (IS_WINDOW (window)); - - priv = window->priv; - g_return_if_fail (priv->mode == WINDOW_MODE_IMAGE); - - g_assert (priv->content != NULL && IS_UI_IMAGE (priv->content)); - ui = UI_IMAGE (priv->content); - - fs = full_screen_new (); - full_screen_set_image (FULL_SCREEN (fs), ui_image_get_image (ui)); - gtk_widget_show (fs); + return priv->content; } diff --git a/src/window.h b/src/window.h index 6231b3ea..465228fb 100644 --- a/src/window.h +++ b/src/window.h @@ -61,14 +61,7 @@ void window_close (Window *window); void window_open_image_dialog (Window *window); gboolean window_open_image (Window *window, const char *filename); -void window_set_zoom (Window *window, double zoom); - -void window_zoom_in (Window *window); -void window_zoom_out (Window *window); -void window_zoom_1 (Window *window); -void window_zoom_fit (Window *window); - -void window_full_screen (Window *window); +GtkWidget *window_get_ui_image (Window *window);