| 672 | | typedef struct |
|---|
| 673 | | { |
|---|
| 674 | | GtkImageView *view; |
|---|
| 675 | | int xsteps[4]; |
|---|
| 676 | | int ysteps[4]; |
|---|
| 677 | | int step_idx; |
|---|
| 678 | | gboolean set_adjustments; |
|---|
| 679 | | gboolean invalidate; |
|---|
| 680 | | } ScrollData; |
|---|
| 681 | | |
|---|
| 682 | | static gboolean |
|---|
| 683 | | gtk_image_view_scroller (gpointer data) |
|---|
| 684 | | { |
|---|
| 685 | | ScrollData *scroll = (ScrollData *) data; |
|---|
| 686 | | GtkImageView *view = scroll->view; |
|---|
| 687 | | |
|---|
| 688 | | scroll->step_idx--; |
|---|
| 689 | | gdouble scroll_x = scroll->xsteps[scroll->step_idx]; |
|---|
| 690 | | gdouble scroll_y = scroll->ysteps[scroll->step_idx]; |
|---|
| 691 | | |
|---|
| 692 | | gdouble new_x = view->offset_x + scroll_x; |
|---|
| 693 | | gdouble new_y = view->offset_y + scroll_y; |
|---|
| 694 | | |
|---|
| 695 | | gtk_image_view_clamp_offset (view, &new_x, &new_y); |
|---|
| 696 | | |
|---|
| 697 | | scroll_x = new_x - view->offset_x; |
|---|
| 698 | | scroll_y = new_y - view->offset_y; |
|---|
| 699 | | |
|---|
| 700 | | view->offset_x += scroll_x; |
|---|
| 701 | | view->offset_y += scroll_y; |
|---|
| 702 | | if (scroll->invalidate) |
|---|
| 703 | | gdk_window_invalidate_rect (GTK_WIDGET (view)->window, NULL, TRUE); |
|---|
| 704 | | else |
|---|
| 705 | | gtk_image_view_fast_scroll (view, scroll_x, scroll_y); |
|---|
| 706 | | gtk_image_view_update_cursor (view); |
|---|
| 707 | | |
|---|
| 708 | | if (scroll->set_adjustments) |
|---|
| 709 | | { |
|---|
| 710 | | g_signal_handlers_block_by_data (G_OBJECT (view->hadj), view); |
|---|
| 711 | | g_signal_handlers_block_by_data (G_OBJECT (view->vadj), view); |
|---|
| 712 | | gtk_adjustment_set_value (view->hadj, view->offset_x); |
|---|
| 713 | | gtk_adjustment_set_value (view->vadj, view->offset_y); |
|---|
| 714 | | g_signal_handlers_unblock_by_data (G_OBJECT (view->hadj), view); |
|---|
| 715 | | g_signal_handlers_unblock_by_data (G_OBJECT (view->vadj), view); |
|---|
| 716 | | } |
|---|
| 717 | | |
|---|
| 718 | | return scroll->step_idx; |
|---|
| 719 | | } |
|---|
| 720 | | |
|---|
| 721 | | /** |
|---|
| 722 | | * gtk_image_view_slope: |
|---|
| 723 | | * |
|---|
| 724 | | * The explanation for this algorithm is here: |
|---|
| 725 | | * http://mail.python.org/pipermail/python-list/2008-March/482359.html |
|---|
| 726 | | * Thank you, Arnaud Delobelle! |
|---|
| 727 | | **/ |
|---|
| 728 | | static void |
|---|
| 729 | | gtk_image_view_slope (int dist, |
|---|
| 730 | | int parts, |
|---|
| 731 | | int *steps) |
|---|
| 732 | | { |
|---|
| 733 | | for (int n = 0; n < parts; n++) |
|---|
| 734 | | steps[n] = (n + 1) * dist / parts - n * dist / parts; |
|---|
| 735 | | } |
|---|
| 736 | | |
|---|
| 752 | | gtk_image_view_scroll_to2 (GtkImageView *view, |
|---|
| 753 | | gdouble offset_x, |
|---|
| 754 | | gdouble offset_y, |
|---|
| 755 | | gboolean set_adjustments, |
|---|
| 756 | | gboolean invalidate, |
|---|
| 757 | | gboolean smooth) |
|---|
| 758 | | { |
|---|
| 759 | | if (!GTK_WIDGET (view)->window) |
|---|
| 760 | | return; |
|---|
| | 686 | gtk_image_view_scroll_to (GtkImageView *view, |
|---|
| | 687 | gdouble offset_x, |
|---|
| | 688 | gdouble offset_y, |
|---|
| | 689 | gboolean set_adjustments, |
|---|
| | 690 | gboolean invalidate) |
|---|
| | 691 | { |
|---|
| | 692 | /* The offset needs to be truncated, otherwise weird rounding |
|---|
| | 693 | errors occur. */ |
|---|
| | 694 | offset_x = (int) offset_x; |
|---|
| | 695 | offset_y = (int) offset_y; |
|---|
| | 696 | |
|---|
| | 697 | gtk_image_view_clamp_offset (view, &offset_x, &offset_y); |
|---|
| 770 | | ScrollData *scroll = g_new0 (ScrollData, 1); |
|---|
| 771 | | scroll->view = view; |
|---|
| 772 | | scroll->step_idx = 1; |
|---|
| 773 | | if (smooth) |
|---|
| 774 | | scroll->step_idx = 4; |
|---|
| 775 | | gtk_image_view_slope (delta_x, scroll->step_idx, scroll->xsteps); |
|---|
| 776 | | gtk_image_view_slope (delta_y, scroll->step_idx, scroll->ysteps); |
|---|
| 777 | | scroll->set_adjustments = set_adjustments; |
|---|
| 778 | | scroll->invalidate = invalidate; |
|---|
| 779 | | |
|---|
| 780 | | if (smooth) |
|---|
| 781 | | { |
|---|
| 782 | | g_timeout_add_full (G_PRIORITY_DEFAULT, |
|---|
| 783 | | 20, |
|---|
| 784 | | gtk_image_view_scroller, |
|---|
| 785 | | scroll, |
|---|
| 786 | | g_free); |
|---|
| 787 | | } |
|---|
| 788 | | else |
|---|
| 789 | | { |
|---|
| 790 | | gtk_image_view_scroller (scroll); |
|---|
| 791 | | g_free (scroll); |
|---|
| 792 | | } |
|---|
| 793 | | } |
|---|
| 794 | | |
|---|
| | 707 | view->offset_x = offset_x; |
|---|
| | 708 | view->offset_y = offset_y; |
|---|
| | 709 | gtk_image_view_update_cursor (view); |
|---|
| | 710 | |
|---|
| | 711 | if (GTK_WIDGET (view)->window) |
|---|
| | 712 | { |
|---|
| | 713 | if (invalidate) |
|---|
| | 714 | gdk_window_invalidate_rect (GTK_WIDGET (view)->window, NULL, TRUE); |
|---|
| | 715 | else |
|---|
| | 716 | gtk_image_view_fast_scroll (view, delta_x, delta_y); |
|---|
| | 717 | } |
|---|
| | 718 | |
|---|
| | 719 | if (!set_adjustments) |
|---|
| | 720 | return; |
|---|
| | 721 | |
|---|
| | 722 | g_signal_handlers_block_by_data (G_OBJECT (view->hadj), view); |
|---|
| | 723 | g_signal_handlers_block_by_data (G_OBJECT (view->vadj), view); |
|---|
| | 724 | gtk_adjustment_set_value (view->hadj, view->offset_x); |
|---|
| | 725 | gtk_adjustment_set_value (view->vadj, view->offset_y); |
|---|
| | 726 | g_signal_handlers_unblock_by_data (G_OBJECT (view->hadj), view); |
|---|
| | 727 | g_signal_handlers_unblock_by_data (G_OBJECT (view->vadj), view); |
|---|
| | 728 | } |
|---|