diff options
Diffstat (limited to '')
-rw-r--r-- | app/display/gimpnavigationeditor.c | 890 |
1 files changed, 890 insertions, 0 deletions
diff --git a/app/display/gimpnavigationeditor.c b/app/display/gimpnavigationeditor.c new file mode 100644 index 0000000..a518882 --- /dev/null +++ b/app/display/gimpnavigationeditor.c @@ -0,0 +1,890 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpnavigationeditor.c + * Copyright (C) 2001 Michael Natterer <mitch@gimp.org> + * + * partly based on app/nav_window + * Copyright (C) 1999 Andy Thomas <alt@gimp.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 3 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, see <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <gegl.h> +#include <gtk/gtk.h> + +#include "libgimpmath/gimpmath.h" +#include "libgimpwidgets/gimpwidgets.h" + +#include "display-types.h" + +#include "config/gimpdisplayconfig.h" + +#include "core/gimp.h" +#include "core/gimpcontext.h" +#include "core/gimpimage.h" +#include "core/gimpimageproxy.h" + +#include "widgets/gimpdocked.h" +#include "widgets/gimphelp-ids.h" +#include "widgets/gimpmenufactory.h" +#include "widgets/gimpnavigationview.h" +#include "widgets/gimpuimanager.h" +#include "widgets/gimpviewrenderer.h" + +#include "gimpdisplay.h" +#include "gimpdisplayshell.h" +#include "gimpdisplayshell-appearance.h" +#include "gimpdisplayshell-scale.h" +#include "gimpdisplayshell-scroll.h" +#include "gimpdisplayshell-transform.h" +#include "gimpnavigationeditor.h" + +#include "gimp-intl.h" + + +#define UPDATE_DELAY 300 /* From GtkRange in GTK+ 2.22 */ + + +static void gimp_navigation_editor_docked_iface_init (GimpDockedInterface *iface); + +static void gimp_navigation_editor_dispose (GObject *object); + +static void gimp_navigation_editor_set_context (GimpDocked *docked, + GimpContext *context); + +static GtkWidget * gimp_navigation_editor_new_private (GimpMenuFactory *menu_factory, + GimpDisplayShell *shell); + +static void gimp_navigation_editor_set_shell (GimpNavigationEditor *editor, + GimpDisplayShell *shell); +static gboolean gimp_navigation_editor_button_release (GtkWidget *widget, + GdkEventButton *bevent, + GimpDisplayShell *shell); +static void gimp_navigation_editor_marker_changed (GimpNavigationView *view, + gdouble center_x, + gdouble center_y, + gdouble width, + gdouble height, + GimpNavigationEditor *editor); +static void gimp_navigation_editor_zoom (GimpNavigationView *view, + GimpZoomType direction, + GimpNavigationEditor *editor); +static void gimp_navigation_editor_scroll (GimpNavigationView *view, + GdkScrollDirection direction, + GimpNavigationEditor *editor); + +static void gimp_navigation_editor_zoom_adj_changed (GtkAdjustment *adj, + GimpNavigationEditor *editor); + +static void gimp_navigation_editor_shell_infinite_canvas_notify (GimpDisplayShell *shell, + const GParamSpec *pspec, + GimpNavigationEditor *editor); +static void gimp_navigation_editor_shell_scaled (GimpDisplayShell *shell, + GimpNavigationEditor *editor); +static void gimp_navigation_editor_shell_scrolled (GimpDisplayShell *shell, + GimpNavigationEditor *editor); +static void gimp_navigation_editor_shell_rotated (GimpDisplayShell *shell, + GimpNavigationEditor *editor); +static void gimp_navigation_editor_shell_reconnect (GimpDisplayShell *shell, + GimpNavigationEditor *editor); + +static void gimp_navigation_editor_viewable_size_changed (GimpViewable *viewable, + GimpNavigationEditor *editor); + +static void gimp_navigation_editor_options_show_canvas_notify (GimpDisplayOptions *options, + const GParamSpec *pspec, + GimpNavigationEditor *editor); + +static void gimp_navigation_editor_update_marker (GimpNavigationEditor *editor); + + +G_DEFINE_TYPE_WITH_CODE (GimpNavigationEditor, gimp_navigation_editor, + GIMP_TYPE_EDITOR, + G_IMPLEMENT_INTERFACE (GIMP_TYPE_DOCKED, + gimp_navigation_editor_docked_iface_init)) + +#define parent_class gimp_navigation_editor_parent_class + + +static void +gimp_navigation_editor_class_init (GimpNavigationEditorClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = gimp_navigation_editor_dispose; +} + +static void +gimp_navigation_editor_docked_iface_init (GimpDockedInterface *iface) +{ + iface->set_context = gimp_navigation_editor_set_context; +} + +static void +gimp_navigation_editor_init (GimpNavigationEditor *editor) +{ + GtkWidget *frame; + + editor->context = NULL; + editor->shell = NULL; + editor->scale_timeout = 0; + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (editor), frame, TRUE, TRUE, 0); + gtk_widget_show (frame); + + editor->view = gimp_view_new_by_types (NULL, + GIMP_TYPE_NAVIGATION_VIEW, + GIMP_TYPE_IMAGE_PROXY, + GIMP_VIEW_SIZE_MEDIUM, 0, TRUE); + gtk_container_add (GTK_CONTAINER (frame), editor->view); + gtk_widget_show (editor->view); + + g_signal_connect (editor->view, "marker-changed", + G_CALLBACK (gimp_navigation_editor_marker_changed), + editor); + g_signal_connect (editor->view, "zoom", + G_CALLBACK (gimp_navigation_editor_zoom), + editor); + g_signal_connect (editor->view, "scroll", + G_CALLBACK (gimp_navigation_editor_scroll), + editor); + + gtk_widget_set_sensitive (GTK_WIDGET (editor), FALSE); +} + +static void +gimp_navigation_editor_dispose (GObject *object) +{ + GimpNavigationEditor *editor = GIMP_NAVIGATION_EDITOR (object); + + if (editor->shell) + gimp_navigation_editor_set_shell (editor, NULL); + + if (editor->scale_timeout) + { + g_source_remove (editor->scale_timeout); + editor->scale_timeout = 0; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gimp_navigation_editor_display_changed (GimpContext *context, + GimpDisplay *display, + GimpNavigationEditor *editor) +{ + GimpDisplayShell *shell = NULL; + + if (display && gimp_display_get_image (display)) + shell = gimp_display_get_shell (display); + + gimp_navigation_editor_set_shell (editor, shell); +} + +static void +gimp_navigation_editor_image_chaged (GimpContext *context, + GimpImage *image, + GimpNavigationEditor *editor) +{ + GimpDisplay *display = gimp_context_get_display (context); + GimpDisplayShell *shell = NULL; + + if (display && image) + shell = gimp_display_get_shell (display); + + gimp_navigation_editor_set_shell (editor, shell); +} + +static void +gimp_navigation_editor_set_context (GimpDocked *docked, + GimpContext *context) +{ + GimpNavigationEditor *editor = GIMP_NAVIGATION_EDITOR (docked); + GimpDisplay *display = NULL; + + if (editor->context) + { + g_signal_handlers_disconnect_by_func (editor->context, + gimp_navigation_editor_display_changed, + editor); + g_signal_handlers_disconnect_by_func (editor->context, + gimp_navigation_editor_image_chaged, + editor); + } + + editor->context = context; + + if (editor->context) + { + g_signal_connect (context, "display-changed", + G_CALLBACK (gimp_navigation_editor_display_changed), + editor); + /* make sure to also call gimp_navigation_editor_set_shell() when the + * last image is closed, even though the display isn't changed, so that + * the editor is properly cleared. + */ + g_signal_connect (context, "image-changed", + G_CALLBACK (gimp_navigation_editor_image_chaged), + editor); + + display = gimp_context_get_display (context); + } + + gimp_view_renderer_set_context (GIMP_VIEW (editor->view)->renderer, + context); + + gimp_navigation_editor_display_changed (editor->context, + display, + editor); +} + + +/* public functions */ + +GtkWidget * +gimp_navigation_editor_new (GimpMenuFactory *menu_factory) +{ + return gimp_navigation_editor_new_private (menu_factory, NULL); +} + +void +gimp_navigation_editor_popup (GimpDisplayShell *shell, + GtkWidget *widget, + gint click_x, + gint click_y) +{ + GtkStyle *style = gtk_widget_get_style (widget); + GimpNavigationEditor *editor; + GimpNavigationView *view; + GdkScreen *screen; + gint x, y; + gint view_marker_center_x, view_marker_center_y; + gint view_marker_width, view_marker_height; + + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (! shell->nav_popup) + { + GtkWidget *frame; + + shell->nav_popup = gtk_window_new (GTK_WINDOW_POPUP); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); + gtk_container_add (GTK_CONTAINER (shell->nav_popup), frame); + gtk_widget_show (frame); + + editor = + GIMP_NAVIGATION_EDITOR (gimp_navigation_editor_new_private (NULL, + shell)); + gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET (editor)); + gtk_widget_show (GTK_WIDGET (editor)); + + g_signal_connect (editor->view, "button-release-event", + G_CALLBACK (gimp_navigation_editor_button_release), + shell); + } + else + { + GtkWidget *bin = gtk_bin_get_child (GTK_BIN (shell->nav_popup)); + + editor = GIMP_NAVIGATION_EDITOR (gtk_bin_get_child (GTK_BIN (bin))); + } + + view = GIMP_NAVIGATION_VIEW (editor->view); + + /* Set poup screen */ + screen = gtk_widget_get_screen (widget); + gtk_window_set_screen (GTK_WINDOW (shell->nav_popup), screen); + + gimp_navigation_view_get_local_marker (view, + &view_marker_center_x, + &view_marker_center_y, + &view_marker_width, + &view_marker_height); + /* Position the popup */ + { + gint x_origin, y_origin; + gint popup_width, popup_height; + gint border_width, border_height; + gint screen_click_x, screen_click_y; + + gdk_window_get_origin (gtk_widget_get_window (widget), + &x_origin, &y_origin); + + screen_click_x = x_origin + click_x; + screen_click_y = y_origin + click_y; + border_width = 2 * style->xthickness; + border_height = 2 * style->ythickness; + popup_width = GIMP_VIEW (view)->renderer->width - 2 * border_width; + popup_height = GIMP_VIEW (view)->renderer->height - 2 * border_height; + + x = screen_click_x - + border_width - + view_marker_center_x; + + y = screen_click_y - + border_height - + view_marker_center_y; + + /* When the image is zoomed out and overscrolled, the above + * calculation risks positioning the popup far far away from the + * click coordinate. We don't want that, so perform some clamping. + */ + x = CLAMP (x, screen_click_x - popup_width, screen_click_x); + y = CLAMP (y, screen_click_y - popup_height, screen_click_y); + + /* If the popup doesn't fit into the screen, we have a problem. + * We move the popup onscreen and risk that the pointer is not + * in the square representing the viewable area anymore. Moving + * the pointer will make the image scroll by a large amount, + * but then it works as usual. Probably better than a popup that + * is completely unusable in the lower right of the screen. + * + * Warping the pointer would be another solution ... + */ + x = CLAMP (x, 0, gdk_screen_get_width (screen) - popup_width); + y = CLAMP (y, 0, gdk_screen_get_height (screen) - popup_height); + + gtk_window_move (GTK_WINDOW (shell->nav_popup), x, y); + } + + gtk_widget_show (shell->nav_popup); + gdk_flush (); + + /* fill in then grab pointer */ + gimp_navigation_view_set_motion_offset (view, 0, 0); + gimp_navigation_view_grab_pointer (view); +} + + +/* private functions */ + +static GtkWidget * +gimp_navigation_editor_new_private (GimpMenuFactory *menu_factory, + GimpDisplayShell *shell) +{ + GimpNavigationEditor *editor; + + g_return_val_if_fail (menu_factory == NULL || + GIMP_IS_MENU_FACTORY (menu_factory), NULL); + g_return_val_if_fail (shell == NULL || GIMP_IS_DISPLAY_SHELL (shell), NULL); + g_return_val_if_fail (menu_factory || shell, NULL); + + if (shell) + { + Gimp *gimp = shell->display->gimp; + GimpDisplayConfig *config = shell->display->config; + GimpView *view; + + editor = g_object_new (GIMP_TYPE_NAVIGATION_EDITOR, NULL); + + view = GIMP_VIEW (editor->view); + + gimp_view_renderer_set_size (view->renderer, + config->nav_preview_size * 3, + view->renderer->border_width); + gimp_view_renderer_set_context (view->renderer, + gimp_get_user_context (gimp)); + gimp_view_renderer_set_color_config (view->renderer, + gimp_display_shell_get_color_config (shell)); + + gimp_navigation_editor_set_shell (editor, shell); + + } + else + { + GtkWidget *hscale; + GtkWidget *hbox; + + editor = g_object_new (GIMP_TYPE_NAVIGATION_EDITOR, + "menu-factory", menu_factory, + "menu-identifier", "<NavigationEditor>", + NULL); + + gtk_widget_set_size_request (editor->view, + GIMP_VIEW_SIZE_HUGE, + GIMP_VIEW_SIZE_HUGE); + gimp_view_set_expand (GIMP_VIEW (editor->view), TRUE); + + /* the editor buttons */ + + editor->zoom_out_button = + gimp_editor_add_action_button (GIMP_EDITOR (editor), "view", + "view-zoom-out", NULL); + + editor->zoom_in_button = + gimp_editor_add_action_button (GIMP_EDITOR (editor), "view", + "view-zoom-in", NULL); + + editor->zoom_100_button = + gimp_editor_add_action_button (GIMP_EDITOR (editor), "view", + "view-zoom-1-1", NULL); + + editor->zoom_fit_in_button = + gimp_editor_add_action_button (GIMP_EDITOR (editor), "view", + "view-zoom-fit-in", NULL); + + editor->zoom_fill_button = + gimp_editor_add_action_button (GIMP_EDITOR (editor), "view", + "view-zoom-fill", NULL); + + editor->shrink_wrap_button = + gimp_editor_add_action_button (GIMP_EDITOR (editor), "view", + "view-shrink-wrap", NULL); + + /* the zoom scale */ + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_box_pack_end (GTK_BOX (editor), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + editor->zoom_adjustment = + GTK_ADJUSTMENT (gtk_adjustment_new (0.0, -8.0, 8.0, 0.5, 1.0, 0.0)); + + g_signal_connect (editor->zoom_adjustment, "value-changed", + G_CALLBACK (gimp_navigation_editor_zoom_adj_changed), + editor); + + hscale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, + editor->zoom_adjustment); + gtk_scale_set_draw_value (GTK_SCALE (hscale), FALSE); + gtk_box_pack_start (GTK_BOX (hbox), hscale, TRUE, TRUE, 0); + gtk_widget_show (hscale); + + /* the zoom label */ + + editor->zoom_label = gtk_label_new ("100%"); + gtk_label_set_width_chars (GTK_LABEL (editor->zoom_label), 7); + gtk_box_pack_start (GTK_BOX (hbox), editor->zoom_label, FALSE, FALSE, 0); + gtk_widget_show (editor->zoom_label); + } + + gimp_view_renderer_set_background (GIMP_VIEW (editor->view)->renderer, + GIMP_ICON_TEXTURE); + + return GTK_WIDGET (editor); +} + +static void +gimp_navigation_editor_set_shell (GimpNavigationEditor *editor, + GimpDisplayShell *shell) +{ + g_return_if_fail (GIMP_IS_NAVIGATION_EDITOR (editor)); + g_return_if_fail (! shell || GIMP_IS_DISPLAY_SHELL (shell)); + + if (shell == editor->shell) + return; + + if (editor->shell) + { + g_signal_handlers_disconnect_by_func (editor->shell, + gimp_navigation_editor_shell_infinite_canvas_notify, + editor); + g_signal_handlers_disconnect_by_func (editor->shell, + gimp_navigation_editor_shell_scaled, + editor); + g_signal_handlers_disconnect_by_func (editor->shell, + gimp_navigation_editor_shell_scrolled, + editor); + g_signal_handlers_disconnect_by_func (editor->shell, + gimp_navigation_editor_shell_rotated, + editor); + g_signal_handlers_disconnect_by_func (editor->shell, + gimp_navigation_editor_shell_reconnect, + editor); + + g_signal_handlers_disconnect_by_func (editor->shell->options, + gimp_navigation_editor_options_show_canvas_notify, + editor); + g_signal_handlers_disconnect_by_func (editor->shell->fullscreen_options, + gimp_navigation_editor_options_show_canvas_notify, + editor); + } + else if (shell) + { + gtk_widget_set_sensitive (GTK_WIDGET (editor), TRUE); + } + + editor->shell = shell; + + if (editor->shell) + { + GimpImage *image = gimp_display_get_image (shell->display); + + g_clear_object (&editor->image_proxy); + + if (image) + { + editor->image_proxy = gimp_image_proxy_new (image); + + g_signal_connect ( + editor->image_proxy, "size-changed", + G_CALLBACK (gimp_navigation_editor_viewable_size_changed), + editor); + } + + gimp_view_set_viewable (GIMP_VIEW (editor->view), + GIMP_VIEWABLE (editor->image_proxy)); + + g_signal_connect (editor->shell, "notify::infinite-canvas", + G_CALLBACK (gimp_navigation_editor_shell_infinite_canvas_notify), + editor); + g_signal_connect (editor->shell, "scaled", + G_CALLBACK (gimp_navigation_editor_shell_scaled), + editor); + g_signal_connect (editor->shell, "scrolled", + G_CALLBACK (gimp_navigation_editor_shell_scrolled), + editor); + g_signal_connect (editor->shell, "rotated", + G_CALLBACK (gimp_navigation_editor_shell_rotated), + editor); + g_signal_connect (editor->shell, "reconnect", + G_CALLBACK (gimp_navigation_editor_shell_reconnect), + editor); + + g_signal_connect (editor->shell->options, "notify::show-canvas-boundary", + G_CALLBACK (gimp_navigation_editor_options_show_canvas_notify), + editor); + g_signal_connect (editor->shell->fullscreen_options, "notify::show-canvas-boundary", + G_CALLBACK (gimp_navigation_editor_options_show_canvas_notify), + editor); + + gimp_navigation_editor_shell_scaled (editor->shell, editor); + } + else + { + gimp_view_set_viewable (GIMP_VIEW (editor->view), NULL); + gtk_widget_set_sensitive (GTK_WIDGET (editor), FALSE); + + g_clear_object (&editor->image_proxy); + } + + if (gimp_editor_get_ui_manager (GIMP_EDITOR (editor))) + gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)), + gimp_editor_get_popup_data (GIMP_EDITOR (editor))); +} + +static gboolean +gimp_navigation_editor_button_release (GtkWidget *widget, + GdkEventButton *bevent, + GimpDisplayShell *shell) +{ + if (bevent->button == 1) + { + gtk_widget_hide (shell->nav_popup); + } + + return FALSE; +} + +static void +gimp_navigation_editor_marker_changed (GimpNavigationView *view, + gdouble center_x, + gdouble center_y, + gdouble width, + gdouble height, + GimpNavigationEditor *editor) +{ + GimpViewRenderer *renderer = GIMP_VIEW (editor->view)->renderer; + + if (editor->shell) + { + if (gimp_display_get_image (editor->shell->display)) + { + GeglRectangle bounding_box; + + bounding_box = gimp_image_proxy_get_bounding_box ( + GIMP_IMAGE_PROXY (renderer->viewable)); + + center_x += bounding_box.x; + center_y += bounding_box.y; + + gimp_display_shell_scroll_center_image_xy (editor->shell, + center_x, center_y); + } + } +} + +static void +gimp_navigation_editor_zoom (GimpNavigationView *view, + GimpZoomType direction, + GimpNavigationEditor *editor) +{ + g_return_if_fail (direction != GIMP_ZOOM_TO); + + if (editor->shell) + { + if (gimp_display_get_image (editor->shell->display)) + gimp_display_shell_scale (editor->shell, + direction, + 0.0, + GIMP_ZOOM_FOCUS_BEST_GUESS); + } +} + +static void +gimp_navigation_editor_scroll (GimpNavigationView *view, + GdkScrollDirection direction, + GimpNavigationEditor *editor) +{ + if (editor->shell) + { + GtkAdjustment *adj = NULL; + gdouble value; + + switch (direction) + { + case GDK_SCROLL_LEFT: + case GDK_SCROLL_RIGHT: + adj = editor->shell->hsbdata; + break; + + case GDK_SCROLL_UP: + case GDK_SCROLL_DOWN: + adj = editor->shell->vsbdata; + break; + } + + gimp_assert (adj != NULL); + + value = gtk_adjustment_get_value (adj); + + switch (direction) + { + case GDK_SCROLL_LEFT: + case GDK_SCROLL_UP: + value -= gtk_adjustment_get_page_increment (adj) / 2; + break; + + case GDK_SCROLL_RIGHT: + case GDK_SCROLL_DOWN: + value += gtk_adjustment_get_page_increment (adj) / 2; + break; + } + + value = CLAMP (value, + gtk_adjustment_get_lower (adj), + gtk_adjustment_get_upper (adj) - + gtk_adjustment_get_page_size (adj)); + + gtk_adjustment_set_value (adj, value); + } +} + +static gboolean +gimp_navigation_editor_zoom_adj_changed_timeout (gpointer data) +{ + GimpNavigationEditor *editor = GIMP_NAVIGATION_EDITOR (data); + GtkAdjustment *adj = editor->zoom_adjustment; + + if (gimp_display_get_image (editor->shell->display)) + gimp_display_shell_scale (editor->shell, + GIMP_ZOOM_TO, + pow (2.0, gtk_adjustment_get_value (adj)), + GIMP_ZOOM_FOCUS_BEST_GUESS); + + editor->scale_timeout = 0; + + return FALSE; +} + +static void +gimp_navigation_editor_zoom_adj_changed (GtkAdjustment *adj, + GimpNavigationEditor *editor) +{ + if (editor->scale_timeout) + g_source_remove (editor->scale_timeout); + + editor->scale_timeout = + g_timeout_add (UPDATE_DELAY, + gimp_navigation_editor_zoom_adj_changed_timeout, + editor); +} + +static void +gimp_navigation_editor_shell_infinite_canvas_notify (GimpDisplayShell *shell, + const GParamSpec *pspec, + GimpNavigationEditor *editor) +{ + gimp_navigation_editor_update_marker (editor); + + if (gimp_editor_get_ui_manager (GIMP_EDITOR (editor))) + gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)), + gimp_editor_get_popup_data (GIMP_EDITOR (editor))); +} + +static void +gimp_navigation_editor_shell_scaled (GimpDisplayShell *shell, + GimpNavigationEditor *editor) +{ + if (editor->zoom_label) + { + gchar *str; + + g_object_get (shell->zoom, + "percentage", &str, + NULL); + gtk_label_set_text (GTK_LABEL (editor->zoom_label), str); + g_free (str); + } + + if (editor->zoom_adjustment) + { + gdouble val; + + val = log (gimp_zoom_model_get_factor (shell->zoom)) / G_LN2; + + g_signal_handlers_block_by_func (editor->zoom_adjustment, + gimp_navigation_editor_zoom_adj_changed, + editor); + + gtk_adjustment_set_value (editor->zoom_adjustment, val); + + g_signal_handlers_unblock_by_func (editor->zoom_adjustment, + gimp_navigation_editor_zoom_adj_changed, + editor); + } + + gimp_navigation_editor_update_marker (editor); + + if (gimp_editor_get_ui_manager (GIMP_EDITOR (editor))) + gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)), + gimp_editor_get_popup_data (GIMP_EDITOR (editor))); +} + +static void +gimp_navigation_editor_shell_scrolled (GimpDisplayShell *shell, + GimpNavigationEditor *editor) +{ + gimp_navigation_editor_update_marker (editor); + + if (gimp_editor_get_ui_manager (GIMP_EDITOR (editor))) + gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)), + gimp_editor_get_popup_data (GIMP_EDITOR (editor))); +} + +static void +gimp_navigation_editor_shell_rotated (GimpDisplayShell *shell, + GimpNavigationEditor *editor) +{ + gimp_navigation_editor_update_marker (editor); + + if (gimp_editor_get_ui_manager (GIMP_EDITOR (editor))) + gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)), + gimp_editor_get_popup_data (GIMP_EDITOR (editor))); +} + +static void +gimp_navigation_editor_viewable_size_changed (GimpViewable *viewable, + GimpNavigationEditor *editor) +{ + gimp_navigation_editor_update_marker (editor); + + if (gimp_editor_get_ui_manager (GIMP_EDITOR (editor))) + gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)), + gimp_editor_get_popup_data (GIMP_EDITOR (editor))); +} + +static void +gimp_navigation_editor_options_show_canvas_notify (GimpDisplayOptions *options, + const GParamSpec *pspec, + GimpNavigationEditor *editor) +{ + gimp_navigation_editor_update_marker (editor); +} + +static void +gimp_navigation_editor_shell_reconnect (GimpDisplayShell *shell, + GimpNavigationEditor *editor) +{ + GimpImage *image = gimp_display_get_image (shell->display); + + g_clear_object (&editor->image_proxy); + + if (image) + { + editor->image_proxy = gimp_image_proxy_new (image); + + g_signal_connect ( + editor->image_proxy, "size-changed", + G_CALLBACK (gimp_navigation_editor_viewable_size_changed), + editor); + } + + gimp_view_set_viewable (GIMP_VIEW (editor->view), + GIMP_VIEWABLE (editor->image_proxy)); + + if (gimp_editor_get_ui_manager (GIMP_EDITOR (editor))) + gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)), + gimp_editor_get_popup_data (GIMP_EDITOR (editor))); +} + +static void +gimp_navigation_editor_update_marker (GimpNavigationEditor *editor) +{ + GimpViewRenderer *renderer = GIMP_VIEW (editor->view)->renderer; + GimpDisplayShell *shell = editor->shell; + + if (renderer->dot_for_dot != shell->dot_for_dot) + gimp_view_renderer_set_dot_for_dot (renderer, shell->dot_for_dot); + + if (renderer->viewable) + { + GimpNavigationView *view = GIMP_NAVIGATION_VIEW (editor->view); + GimpImage *image; + GeglRectangle bounding_box; + gdouble x, y; + gdouble w, h; + + image = gimp_image_proxy_get_image ( + GIMP_IMAGE_PROXY (renderer->viewable)); + + gimp_image_proxy_set_show_all ( + GIMP_IMAGE_PROXY (renderer->viewable), + gimp_display_shell_get_infinite_canvas (shell)); + + bounding_box = gimp_image_proxy_get_bounding_box ( + GIMP_IMAGE_PROXY (renderer->viewable)); + + gimp_display_shell_scroll_get_viewport (shell, &x, &y, &w, &h); + gimp_display_shell_untransform_xy_f (shell, + shell->disp_width / 2, + shell->disp_height / 2, + &x, &y); + + x -= bounding_box.x; + y -= bounding_box.y; + + gimp_navigation_view_set_marker (view, + x, y, w, h, + shell->flip_horizontally, + shell->flip_vertically, + shell->rotate_angle); + + gimp_navigation_view_set_canvas ( + view, + gimp_display_shell_get_infinite_canvas (shell) && + gimp_display_shell_get_show_canvas (shell), + -bounding_box.x, -bounding_box.y, + gimp_image_get_width (image), gimp_image_get_height (image)); + } +} |