static void image_view_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { ImageView *image_view = IMAGE_VIEW (object); ImageViewPrivate *priv = image_view->priv; switch (property_id) { case PROP_INTERP_TYPE: g_value_set_int (value, priv->interp_type); break; case PROP_CHECK_TYPE: g_value_set_int (value, priv->check_type); break; case PROP_CHECK_SIZE: g_value_set_int (value, priv->check_size); break; case PROP_DITHER: g_value_set_int (value, priv->dither); break; default: g_warning ("unknown property id `%d'", property_id); break; } }
static void accessible_image_view_get_image_size (AtkImage *obj, gint *width, gint *height) { GtkWidget *widget; GdkPixbuf *image; widget = GTK_ACCESSIBLE (obj)->widget; if (widget == 0) { /* * State is defunct */ *width = -1; *height = -1; return; } image = image_view_get_pixbuf (IMAGE_VIEW (widget)); *height = gdk_pixbuf_get_height(image); *width = gdk_pixbuf_get_width(image); }
static void image_view_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { ImageView *image_view = IMAGE_VIEW (object); switch (property_id) { case PROP_INTERP_TYPE: image_view_set_interp_type (image_view, g_value_get_int (value)); break; case PROP_CHECK_TYPE: image_view_set_check_type (image_view, g_value_get_int (value)); break; case PROP_CHECK_SIZE: image_view_set_check_size (image_view, g_value_get_int (value)); break; case PROP_DITHER: image_view_set_dither (image_view, g_value_get_int (value)); break; default: g_warning ("unknown property id `%d'", property_id); break; } }
/* Idle handler for the drawing process. We pull a rectangle from the dirty * region microtile array, paint it, and leave the rest to the next idle * iteration. */ static gboolean paint_iteration_idle (gpointer data) { ImageView *view; ImageViewPrivate *priv; ArtIRect rect; view = IMAGE_VIEW (data); priv = view->priv; g_assert (priv->uta != NULL); pull_rectangle (priv->uta, &rect, PAINT_RECT_WIDTH, PAINT_RECT_HEIGHT); if (art_irect_empty (&rect)) { art_uta_free (priv->uta); priv->uta = NULL; } else paint_rectangle (view, &rect, priv->interp_type); if (!priv->uta) { priv->idle_id = 0; return FALSE; } return TRUE; }
/* Destroy handler for the image view */ static void image_view_dispose (GObject *object) { ImageView *view; ImageViewPrivate *priv; view = IMAGE_VIEW (object); priv = view->priv; g_signal_handlers_disconnect_matched ( priv->hadj, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view); g_signal_handlers_disconnect_matched ( priv->vadj, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view); /* Clean up */ if (view->priv->pixbuf) g_object_unref (G_OBJECT (view->priv->pixbuf)); view->priv->pixbuf = NULL; remove_dirty_region (view); GNOME_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); }
/* Unrealize handler for the image view */ static void image_view_unrealize (GtkWidget *widget) { g_return_if_fail (widget != NULL); g_return_if_fail (IS_IMAGE_VIEW (widget)); remove_dirty_region (IMAGE_VIEW (widget)); if (GTK_WIDGET_CLASS (parent_class)->unrealize) (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); }
/* Callback used when an adjustment is changed */ static void adjustment_changed_cb (GtkAdjustment *adj, gpointer data) { ImageView *view; ImageViewPrivate *priv; view = IMAGE_VIEW (data); priv = view->priv; scroll_to (view, priv->hadj->value, priv->vadj->value, FALSE); }
/* Scroll event handler for the image view. We zoom with an event without * modifiers rather than scroll; we use the Shift modifier to scroll. * Rationale: images are not primarily vertical, and in EOG you scan scroll by * dragging the image with button 1 anyways. */ static gboolean image_view_scroll_event (GtkWidget *widget, GdkEventScroll *event) { ImageView *view; ImageViewPrivate *priv; double zoom_factor; int xofs, yofs; view = IMAGE_VIEW (widget); priv = view->priv; /* Compute zoom factor and scrolling offsets; we'll only use either of them */ xofs = priv->hadj->page_increment / 2; /* same as in gtkscrolledwindow.c */ yofs = priv->vadj->page_increment / 2; switch (event->direction) { case GDK_SCROLL_UP: zoom_factor = IMAGE_VIEW_ZOOM_MULTIPLIER; xofs = 0; yofs = -yofs; break; case GDK_SCROLL_LEFT: zoom_factor = 1.0 / IMAGE_VIEW_ZOOM_MULTIPLIER; xofs = -xofs; yofs = 0; break; case GDK_SCROLL_DOWN: zoom_factor = 1.0 / IMAGE_VIEW_ZOOM_MULTIPLIER; xofs = 0; yofs = yofs; break; case GDK_SCROLL_RIGHT: zoom_factor = IMAGE_VIEW_ZOOM_MULTIPLIER; xofs = xofs; yofs = 0; break; default: g_assert_not_reached (); return FALSE; } if ((event->state & GDK_SHIFT_MASK) == 0) image_view_set_zoom (view, priv->zoomx * zoom_factor, priv->zoomy * zoom_factor, TRUE, event->x, event->y); else scroll_by (view, xofs, yofs); return TRUE; }
/* Button press event handler for the image view */ static gboolean image_view_button_press_event (GtkWidget *widget, GdkEventButton *event) { ImageView *view; ImageViewPrivate *priv; GdkCursor *cursor; view = IMAGE_VIEW (widget); priv = view->priv; if (!GTK_WIDGET_HAS_FOCUS (widget)) gtk_widget_grab_focus (widget); if (priv->dragging) return FALSE; switch (event->button) { case 1: cursor = cursor_get (widget, CURSOR_HAND_CLOSED); gdk_window_set_cursor (widget->window, cursor); gdk_cursor_unref (cursor); priv->dragging = TRUE; priv->drag_anchor_x = event->x; priv->drag_anchor_y = event->y; priv->drag_ofs_x = priv->xofs; priv->drag_ofs_y = priv->yofs; return TRUE; case 4: image_view_set_zoom (view, priv->zoomx * IMAGE_VIEW_ZOOM_MULTIPLIER, priv->zoomy * IMAGE_VIEW_ZOOM_MULTIPLIER, TRUE, event->x, event->y); return TRUE; case 5: image_view_set_zoom (view, priv->zoomx / IMAGE_VIEW_ZOOM_MULTIPLIER, priv->zoomy / IMAGE_VIEW_ZOOM_MULTIPLIER, TRUE, event->x, event->y); return TRUE; default: break; } return FALSE; }
/* Size_request handler for the image view */ static void image_view_size_request (GtkWidget *widget, GtkRequisition *requisition) { ImageView *view; ImageViewPrivate *priv; g_return_if_fail (widget != NULL); g_return_if_fail (IS_IMAGE_VIEW (widget)); g_return_if_fail (requisition != NULL); view = IMAGE_VIEW (widget); priv = view->priv; requisition->width = requisition->height = 0; }
/* Finalize handler for the image view */ static void image_view_finalize (GObject *object) { ImageView *view; ImageViewPrivate *priv; view = IMAGE_VIEW (object); priv = view->priv; g_object_unref (priv->hadj); g_object_unref (priv->vadj); g_free (priv); GNOME_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); }
/* Button release event handler for the image view */ static gboolean image_view_button_release_event (GtkWidget *widget, GdkEventButton *event) { ImageView *view; ImageViewPrivate *priv; GdkCursor *cursor; view = IMAGE_VIEW (widget); priv = view->priv; if (!priv->dragging || event->button != 1) return FALSE; drag_to (view, event->x, event->y); priv->dragging = FALSE; cursor = cursor_get (widget, CURSOR_HAND_OPEN); gdk_window_set_cursor (widget->window, cursor); gdk_cursor_unref (cursor); return TRUE; }
/* Expose event handler for the image view. First we process the whole dirty * region by drawing a non-interpolated version, which is "instantaneous", and * we do this synchronously. Then, if we are set to use interpolation, we queue * an idle handler to handle interpolated drawing there. */ static gboolean image_view_expose_event (GtkWidget *widget, GdkEventExpose *event) { ImageView *view; GdkRectangle *rects; gint n_rects; int i; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (IS_IMAGE_VIEW (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); view = IMAGE_VIEW (widget); gdk_region_get_rectangles (event->region, &rects, &n_rects); for (i = 0; i < n_rects; i++) request_paint_area (view, rects + i); g_free (rects); return TRUE; }
/* Motion event handler for the image view */ static gboolean image_view_motion_event (GtkWidget *widget, GdkEventMotion *event) { ImageView *view; ImageViewPrivate *priv; gint x, y; GdkModifierType mods; view = IMAGE_VIEW (widget); priv = view->priv; if (!priv->dragging) return FALSE; if (event->is_hint) gdk_window_get_pointer (widget->window, &x, &y, &mods); else { x = event->x; y = event->y; } drag_to (view, x, y); return TRUE; }
/* Size_allocate handler for the image view */ static void image_view_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { ImageView *view; ImageViewPrivate *priv; int xofs, yofs; int scaled_width, scaled_height; g_return_if_fail (widget != NULL); g_return_if_fail (IS_IMAGE_VIEW (widget)); g_return_if_fail (allocation != NULL); view = IMAGE_VIEW (widget); priv = view->priv; /* Compute new scroll offsets */ if (priv->need_zoom_change) { compute_center_zoom_offsets (view, widget->allocation.width, widget->allocation.height, allocation->width, allocation->height, &xofs, &yofs); set_default_zoom_anchor (view); priv->need_zoom_change = FALSE; } else { xofs = priv->xofs; yofs = priv->yofs; } /* Resize the window */ widget->allocation = *allocation; if (GTK_WIDGET_REALIZED (widget)) gdk_window_move_resize (widget->window, allocation->x, allocation->y, allocation->width, allocation->height); /* Set scroll increments */ compute_scaled_size (view, priv->zoomx, priv->zoomy, &scaled_width, &scaled_height); priv->hadj->page_size = MIN (scaled_width, allocation->width); priv->hadj->page_increment = allocation->width / 2; priv->hadj->step_increment = SCROLL_STEP_SIZE; priv->vadj->page_size = MIN (scaled_height, allocation->height); priv->vadj->page_increment = allocation->height / 2; priv->vadj->step_increment = SCROLL_STEP_SIZE; /* Set scroll bounds and new offsets */ priv->hadj->lower = 0; priv->hadj->upper = scaled_width; xofs = CLAMP (xofs, 0, priv->hadj->upper - priv->hadj->page_size); priv->vadj->lower = 0; priv->vadj->upper = scaled_height; yofs = CLAMP (yofs, 0, priv->vadj->upper - priv->vadj->page_size); g_signal_emit_by_name (priv->hadj, "changed"); g_signal_emit_by_name (priv->vadj, "changed"); if (priv->hadj->value != xofs) { priv->hadj->value = xofs; priv->xofs = xofs; g_signal_handlers_block_matched ( priv->hadj, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view); g_signal_emit_by_name (priv->hadj, "value_changed"); g_signal_handlers_unblock_matched ( priv->hadj, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view); } if (priv->vadj->value != yofs) { priv->vadj->value = yofs; priv->yofs = yofs; g_signal_handlers_block_matched ( priv->vadj, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view); g_signal_emit_by_name (priv->vadj, "value_changed"); g_signal_handlers_unblock_matched ( priv->vadj, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view); } }
/* Set_scroll_adjustments handler for the image view */ static void image_view_set_scroll_adjustments (GtkWidget *widget, GtkAdjustment *hadj, GtkAdjustment *vadj) { ImageView *view; ImageViewPrivate *priv; gboolean need_adjust; g_return_if_fail (widget != NULL); g_return_if_fail (IS_IMAGE_VIEW (widget)); view = IMAGE_VIEW (widget); priv = view->priv; if (hadj) g_return_if_fail (GTK_IS_ADJUSTMENT (hadj)); else hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); if (vadj) g_return_if_fail (GTK_IS_ADJUSTMENT (vadj)); else vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); if (priv->hadj && priv->hadj != hadj) { g_signal_handlers_disconnect_matched ( priv->hadj, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view); g_object_unref (priv->hadj); } if (priv->vadj && priv->vadj != vadj) { g_signal_handlers_disconnect_matched ( priv->vadj, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view); g_object_unref (priv->vadj); } need_adjust = FALSE; if (priv->hadj != hadj) { priv->hadj = hadj; g_object_ref (priv->hadj); gtk_object_sink (GTK_OBJECT (priv->hadj)); g_signal_connect (priv->hadj, "value_changed", G_CALLBACK (adjustment_changed_cb), view); need_adjust = TRUE; } if (priv->vadj != vadj) { priv->vadj = vadj; g_object_ref (priv->vadj); gtk_object_sink (GTK_OBJECT (priv->vadj)); g_signal_connect (priv->vadj, "value_changed", G_CALLBACK (adjustment_changed_cb), view); need_adjust = TRUE; } if (need_adjust) adjustment_changed_cb (NULL, view); }
/* Key press event handler for the image view */ static gboolean image_view_key_press_event (GtkWidget *widget, GdkEventKey *event) { ImageView *view; ImageViewPrivate *priv; gboolean do_zoom; double zoomx, zoomy; gboolean do_scroll; int xofs, yofs; view = IMAGE_VIEW (widget); priv = view->priv; do_zoom = FALSE; do_scroll = FALSE; xofs = yofs = 0; zoomx = zoomy = 1.0; if ((event->state & (GDK_MODIFIER_MASK & ~GDK_LOCK_MASK)) != 0) return 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_plus: case GDK_KP_Add: do_zoom = TRUE; zoomx = priv->zoomx * IMAGE_VIEW_ZOOM_MULTIPLIER; zoomy = priv->zoomy * IMAGE_VIEW_ZOOM_MULTIPLIER; break; case GDK_minus: case GDK_KP_Subtract: do_zoom = TRUE; zoomx = priv->zoomx / IMAGE_VIEW_ZOOM_MULTIPLIER; zoomy = priv->zoomy / IMAGE_VIEW_ZOOM_MULTIPLIER; break; case GDK_1: do_zoom = TRUE; zoomx = zoomy = 1.0; break; case GDK_F: case GDK_f: g_signal_emit (view, image_view_signals [ZOOM_FIT], 0); break; default: return FALSE; } if (do_zoom) { gint x, y; gdk_window_get_pointer (widget->window, &x, &y, NULL); image_view_set_zoom (view, zoomx, zoomy, TRUE, x, y); } if (do_scroll) scroll_by (view, xofs, yofs); return TRUE; }