app: improve display scroll/zoom-related behavior in "show all" mode

In "show all" mode, the image is thought to be "infinite"; this
commit improves the overall scrolling/zooming behavior in this mode
according to this assumption.  In cases where a specific image size
is needed (e.g., for the scrollbar bounds, fit-image-in-window,
etc.), the image's full bounding box is used; however, in cases
where a center point is needed (e.g., for the zoomed-out scrollbar
bounds, center-image-in-window), the canvas center, rather than the
bounding-box center, is still used.
This commit is contained in:
Ell
2019-09-04 16:11:54 +03:00
parent 1f76013d1e
commit f0b7d0a2e2
9 changed files with 282 additions and 159 deletions

View File

@ -44,6 +44,8 @@
#include "gimpdisplayshell-expose.h" #include "gimpdisplayshell-expose.h"
#include "gimpdisplayshell-handlers.h" #include "gimpdisplayshell-handlers.h"
#include "gimpdisplayshell-icon.h" #include "gimpdisplayshell-icon.h"
#include "gimpdisplayshell-scroll.h"
#include "gimpdisplayshell-scrollbars.h"
#include "gimpdisplayshell-transform.h" #include "gimpdisplayshell-transform.h"
#include "gimpimagewindow.h" #include "gimpimagewindow.h"
@ -807,6 +809,9 @@ gimp_display_update_bounding_box (GimpDisplay *display)
} }
private->bounding_box = bounding_box; private->bounding_box = bounding_box;
gimp_display_shell_scroll_clamp_and_update (shell);
gimp_display_shell_scrollbars_update (shell);
} }
} }
else else

View File

@ -207,9 +207,18 @@ gimp_display_shell_canvas_size_allocate (GtkWidget *widget,
center_horizontally = sw <= shell->disp_width; center_horizontally = sw <= shell->disp_width;
center_vertically = sh <= shell->disp_height; center_vertically = sh <= shell->disp_height;
if (! shell->show_all)
{
gimp_display_shell_scroll_center_image (shell, gimp_display_shell_scroll_center_image (shell,
center_horizontally, center_horizontally,
center_vertically); center_vertically);
}
else
{
gimp_display_shell_scroll_center_content (shell,
center_horizontally,
center_vertically);
}
/* This is basically the best we can do before we get an /* This is basically the best we can do before we get an
* API for storing the image offset at the start of an * API for storing the image offset at the start of an

View File

@ -841,7 +841,11 @@ gimp_display_shell_size_changed_detailed_handler (GimpImage *image,
shell->offset_x + scaled_previous_origin_x, shell->offset_x + scaled_previous_origin_x,
shell->offset_y + scaled_previous_origin_y); shell->offset_y + scaled_previous_origin_y);
gimp_display_shell_scroll_center_image (shell, horizontally, vertically); if (! shell->show_all)
{
gimp_display_shell_scroll_center_image (shell,
horizontally, vertically);
}
/* The above calls might not lead to a call to /* The above calls might not lead to a call to
* gimp_display_shell_scroll_clamp_and_update() and * gimp_display_shell_scroll_clamp_and_update() and

View File

@ -398,7 +398,6 @@ gimp_display_shell_scale_image_is_within_viewport (GimpDisplayShell *shell,
gboolean *horizontally, gboolean *horizontally,
gboolean *vertically) gboolean *vertically)
{ {
gint sw, sh;
gboolean horizontally_dummy, vertically_dummy; gboolean horizontally_dummy, vertically_dummy;
g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE); g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE);
@ -406,15 +405,25 @@ gimp_display_shell_scale_image_is_within_viewport (GimpDisplayShell *shell,
if (! horizontally) horizontally = &horizontally_dummy; if (! horizontally) horizontally = &horizontally_dummy;
if (! vertically) vertically = &vertically_dummy; if (! vertically) vertically = &vertically_dummy;
gimp_display_shell_scale_get_image_size (shell, &sw, &sh); if (! shell->show_all)
{
gint sx, sy;
gint sw, sh;
*horizontally = sw <= shell->disp_width && gimp_display_shell_scale_get_image_bounding_box (shell,
shell->offset_x <= 0 && &sx, &sy, &sw, &sh);
shell->offset_x >= sw - shell->disp_width;
*vertically = sh <= shell->disp_height && sx -= shell->offset_x;
shell->offset_y <= 0 && sy -= shell->offset_y;
shell->offset_y >= sh - shell->disp_height;
*horizontally = sx >= 0 && sx + sw <= shell->disp_width;
*vertically = sy >= 0 && sy + sh <= shell->disp_height;
}
else
{
*horizontally = FALSE;
*vertically = FALSE;
}
return *vertically && *horizontally; return *vertically && *horizontally;
} }
@ -1113,7 +1122,7 @@ static void
gimp_display_shell_scale_fit_or_fill (GimpDisplayShell *shell, gimp_display_shell_scale_fit_or_fill (GimpDisplayShell *shell,
gboolean fill) gboolean fill)
{ {
GimpImage *image; GeglRectangle bounding_box;
gdouble image_x; gdouble image_x;
gdouble image_y; gdouble image_y;
gdouble image_width; gdouble image_width;
@ -1121,14 +1130,17 @@ gimp_display_shell_scale_fit_or_fill (GimpDisplayShell *shell,
gdouble current_scale; gdouble current_scale;
gdouble zoom_factor; gdouble zoom_factor;
image = gimp_display_get_image (shell->display); bounding_box = gimp_display_shell_get_bounding_box (shell);
gimp_display_shell_transform_bounds (shell, gimp_display_shell_transform_bounds (shell,
0, 0, bounding_box.x,
gimp_image_get_width (image), bounding_box.y,
gimp_image_get_height (image), bounding_box.x + bounding_box.width,
&image_x, &image_y, bounding_box.y + bounding_box.height,
&image_width, &image_height); &image_x,
&image_y,
&image_width,
&image_height);
image_width -= image_x; image_width -= image_x;
image_height -= image_y; image_height -= image_y;
@ -1151,7 +1163,7 @@ gimp_display_shell_scale_fit_or_fill (GimpDisplayShell *shell,
zoom_factor * current_scale, zoom_factor * current_scale,
GIMP_ZOOM_FOCUS_BEST_GUESS); GIMP_ZOOM_FOCUS_BEST_GUESS);
gimp_display_shell_scroll_center_image (shell, TRUE, TRUE); gimp_display_shell_scroll_center_content (shell, TRUE, TRUE);
} }
static gboolean static gboolean
@ -1168,7 +1180,7 @@ gimp_display_shell_scale_image_starts_to_fit (GimpDisplayShell *shell,
if (! horizontally) horizontally = &horizontally_dummy; if (! horizontally) horizontally = &horizontally_dummy;
/* The image can only start to fit if we zoom out */ /* The image can only start to fit if we zoom out */
if (new_scale > current_scale) if (new_scale > current_scale || shell->show_all)
{ {
*vertically = FALSE; *vertically = FALSE;
*horizontally = FALSE; *horizontally = FALSE;
@ -1229,16 +1241,19 @@ gimp_display_shell_scale_viewport_coord_almost_centered (GimpDisplayShell *shell
gboolean *horizontally, gboolean *horizontally,
gboolean *vertically) gboolean *vertically)
{ {
gboolean local_horizontally; gboolean local_horizontally = FALSE;
gboolean local_vertically; gboolean local_vertically = FALSE;
gint center_x = shell->disp_width / 2; gint center_x = shell->disp_width / 2;
gint center_y = shell->disp_height / 2; gint center_y = shell->disp_height / 2;
if (! shell->show_all)
{
local_horizontally = (x > center_x - ALMOST_CENTERED_THRESHOLD && local_horizontally = (x > center_x - ALMOST_CENTERED_THRESHOLD &&
x < center_x + ALMOST_CENTERED_THRESHOLD); x < center_x + ALMOST_CENTERED_THRESHOLD);
local_vertically = (y > center_y - ALMOST_CENTERED_THRESHOLD && local_vertically = (y > center_y - ALMOST_CENTERED_THRESHOLD &&
y < center_y + ALMOST_CENTERED_THRESHOLD); y < center_y + ALMOST_CENTERED_THRESHOLD);
}
if (horizontally) *horizontally = local_horizontally; if (horizontally) *horizontally = local_horizontally;
if (vertically) *vertically = local_vertically; if (vertically) *vertically = local_vertically;

View File

@ -159,6 +159,8 @@ gimp_display_shell_scroll_clamp_and_update (GimpDisplayShell *shell)
image = gimp_display_get_image (shell->display); image = gimp_display_get_image (shell->display);
if (image) if (image)
{
if (! shell->show_all)
{ {
gint bounds_x; gint bounds_x;
gint bounds_y; gint bounds_y;
@ -174,8 +176,10 @@ gimp_display_shell_scroll_clamp_and_update (GimpDisplayShell *shell)
gimp_display_shell_rotate_update_transform (shell); gimp_display_shell_rotate_update_transform (shell);
gimp_display_shell_scale_get_image_bounds (shell, gimp_display_shell_scale_get_image_bounds (shell,
&bounds_x, &bounds_y, &bounds_x,
&bounds_width, &bounds_height); &bounds_y,
&bounds_width,
&bounds_height);
if (shell->disp_width < bounds_width) if (shell->disp_width < bounds_width)
{ {
@ -238,6 +242,17 @@ gimp_display_shell_scroll_clamp_and_update (GimpDisplayShell *shell)
min_offset_y, min_offset_y,
max_offset_y); max_offset_y);
} }
else
{
/* Set scrollbar stepper sensitiity */
gimp_display_shell_scrollbars_update_steppers (shell,
G_MININT,
G_MAXINT,
G_MININT,
G_MAXINT);
}
}
else else
{ {
shell->offset_x = 0; shell->offset_x = 0;
@ -278,6 +293,8 @@ gimp_display_shell_scroll_unoverscrollify (GimpDisplayShell *shell,
*out_offset_x = in_offset_x; *out_offset_x = in_offset_x;
*out_offset_y = in_offset_y; *out_offset_y = in_offset_y;
if (! shell->show_all)
{
gimp_display_shell_scale_get_image_size (shell, &sw, &sh); gimp_display_shell_scale_get_image_size (shell, &sw, &sh);
if (in_offset_x < 0) if (in_offset_x < 0)
@ -305,6 +322,7 @@ gimp_display_shell_scroll_unoverscrollify (GimpDisplayShell *shell,
*out_offset_y = MIN (in_offset_y, *out_offset_y = MIN (in_offset_y,
MAX (0, min_offset - shell->offset_y)); MAX (0, min_offset - shell->offset_y));
} }
}
} }
/** /**
@ -389,6 +407,65 @@ gimp_display_shell_scroll_center_image (GimpDisplayShell *shell,
gimp_display_shell_scroll (shell, offset_x, offset_y); gimp_display_shell_scroll (shell, offset_x, offset_y);
} }
/**
* gimp_display_shell_scroll_center_image:
* @shell:
* @horizontally:
* @vertically:
*
* Centers the image content in the display shell on the desired axes.
**/
void
gimp_display_shell_scroll_center_content (GimpDisplayShell *shell,
gboolean horizontally,
gboolean vertically)
{
gint content_x;
gint content_y;
gint content_width;
gint content_height;
gint center_x;
gint center_y;
gint offset_x = 0;
gint offset_y = 0;
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
if (! shell->display ||
! gimp_display_get_image (shell->display) ||
(! vertically && ! horizontally))
return;
gimp_display_shell_scale_get_image_bounding_box (shell,
&content_x,
&content_y,
&content_width,
&content_height);
if (shell->disp_width > content_width)
{
content_x -= (shell->disp_width - content_width) / 2;
content_width = shell->disp_width;
}
if (shell->disp_height > content_height)
{
content_y -= (shell->disp_height - content_height) / 2;
content_height = shell->disp_height;
}
center_x = content_x + content_width / 2;
center_y = content_y + content_height / 2;
if (horizontally)
offset_x = center_x - shell->disp_width / 2 - shell->offset_x;
if (vertically)
offset_y = center_y - shell->disp_height / 2 - shell->offset_y;
gimp_display_shell_scroll (shell, offset_x, offset_y);
}
/** /**
* gimp_display_shell_scroll_get_scaled_viewport: * gimp_display_shell_scroll_get_scaled_viewport:
* @shell: * @shell:

View File

@ -40,6 +40,9 @@ void gimp_display_shell_scroll_center_image_xy (GimpDisplayShell *shell,
void gimp_display_shell_scroll_center_image (GimpDisplayShell *shell, void gimp_display_shell_scroll_center_image (GimpDisplayShell *shell,
gboolean horizontally, gboolean horizontally,
gboolean vertically); gboolean vertically);
void gimp_display_shell_scroll_center_content (GimpDisplayShell *shell,
gboolean horizontally,
gboolean vertically);
void gimp_display_shell_scroll_get_scaled_viewport (GimpDisplayShell *shell, void gimp_display_shell_scroll_get_scaled_viewport (GimpDisplayShell *shell,
gint *x, gint *x,

View File

@ -93,6 +93,10 @@ gimp_display_shell_scrollbars_setup_horizontal (GimpDisplayShell *shell,
{ {
gint bounds_x; gint bounds_x;
gint bounds_width; gint bounds_width;
gint bounding_box_x;
gint bounding_box_width;
gint x1;
gint x2;
gdouble lower; gdouble lower;
gdouble upper; gdouble upper;
gdouble scale_x; gdouble scale_x;
@ -106,14 +110,18 @@ gimp_display_shell_scrollbars_setup_horizontal (GimpDisplayShell *shell,
&bounds_x, NULL, &bounds_x, NULL,
&bounds_width, NULL); &bounds_width, NULL);
if (shell->disp_width > bounds_width) gimp_display_shell_scale_get_image_bounding_box (shell,
{ &bounding_box_x, NULL,
bounds_x -= (shell->disp_width - bounds_width) / 2; &bounding_box_width, NULL);
bounds_width = shell->disp_width;
}
lower = MIN (value, bounds_x); x1 = bounding_box_x;
upper = MAX (value + shell->disp_width, bounds_x + bounds_width); x2 = bounding_box_x + bounding_box_width;
x1 = MIN (x1, bounds_x + bounds_width / 2 - shell->disp_width / 2);
x2 = MAX (x2, bounds_x + bounds_width / 2 + (shell->disp_width + 1) / 2);
lower = MIN (value, x1);
upper = MAX (value + shell->disp_width, x2);
gimp_display_shell_get_rotated_scale (shell, &scale_x, NULL); gimp_display_shell_get_rotated_scale (shell, &scale_x, NULL);
@ -137,6 +145,10 @@ gimp_display_shell_scrollbars_setup_vertical (GimpDisplayShell *shell,
{ {
gint bounds_y; gint bounds_y;
gint bounds_height; gint bounds_height;
gint bounding_box_y;
gint bounding_box_height;
gint y1;
gint y2;
gdouble lower; gdouble lower;
gdouble upper; gdouble upper;
gdouble scale_y; gdouble scale_y;
@ -150,14 +162,18 @@ gimp_display_shell_scrollbars_setup_vertical (GimpDisplayShell *shell,
NULL, &bounds_y, NULL, &bounds_y,
NULL, &bounds_height); NULL, &bounds_height);
if (shell->disp_height > bounds_height) gimp_display_shell_scale_get_image_bounding_box (shell,
{ NULL, &bounding_box_y,
bounds_y -= (shell->disp_height - bounds_height) / 2; NULL, &bounding_box_height);
bounds_height = shell->disp_height;
}
lower = MIN (value, bounds_y); y1 = bounding_box_y;
upper = MAX (value + shell->disp_height, bounds_y + bounds_height); y2 = bounding_box_y + bounding_box_height;
y1 = MIN (y1, bounds_y + bounds_height / 2 - shell->disp_height / 2);
y2 = MAX (y2, bounds_y + bounds_height / 2 + (shell->disp_height + 1) / 2);
lower = MIN (value, y1);
upper = MAX (value + shell->disp_height, y2);
gimp_display_shell_get_rotated_scale (shell, NULL, &scale_y); gimp_display_shell_get_rotated_scale (shell, NULL, &scale_y);

View File

@ -75,6 +75,7 @@
#include "gimpdisplayshell-rulers.h" #include "gimpdisplayshell-rulers.h"
#include "gimpdisplayshell-scale.h" #include "gimpdisplayshell-scale.h"
#include "gimpdisplayshell-scroll.h" #include "gimpdisplayshell-scroll.h"
#include "gimpdisplayshell-scrollbars.h"
#include "gimpdisplayshell-selection.h" #include "gimpdisplayshell-selection.h"
#include "gimpdisplayshell-title.h" #include "gimpdisplayshell-title.h"
#include "gimpdisplayshell-tool-events.h" #include "gimpdisplayshell-tool-events.h"
@ -1848,6 +1849,9 @@ gimp_display_shell_set_show_all (GimpDisplayShell *shell,
gimp_display_update_bounding_box (shell->display); gimp_display_update_bounding_box (shell->display);
gimp_display_shell_scroll_clamp_and_update (shell);
gimp_display_shell_scrollbars_update (shell);
gimp_display_shell_set_priority_viewport (shell); gimp_display_shell_set_priority_viewport (shell);
gimp_display_shell_expose_full (shell); gimp_display_shell_expose_full (shell);

View File

@ -1465,15 +1465,13 @@ gimp_image_window_shrink_wrap (GimpImageWindow *window,
gboolean grow_only) gboolean grow_only)
{ {
GimpDisplayShell *active_shell; GimpDisplayShell *active_shell;
GimpImage *image;
GtkWidget *widget; GtkWidget *widget;
GtkAllocation allocation; GtkAllocation allocation;
GdkScreen *screen; GdkScreen *screen;
GdkRectangle rect; GdkRectangle rect;
gint monitor; gint monitor;
gint disp_width, disp_height; gint disp_width, disp_height;
gdouble x, y; gint width, height;
gdouble width, height;
gint max_auto_width, max_auto_height; gint max_auto_width, max_auto_height;
gint border_width, border_height; gint border_width, border_height;
gboolean resize = FALSE; gboolean resize = FALSE;
@ -1490,8 +1488,6 @@ gimp_image_window_shrink_wrap (GimpImageWindow *window,
if (!active_shell) if (!active_shell)
return; return;
image = gimp_display_get_image (active_shell->display);
widget = GTK_WIDGET (window); widget = GTK_WIDGET (window);
screen = gtk_widget_get_screen (widget); screen = gtk_widget_get_screen (widget);
@ -1501,16 +1497,10 @@ gimp_image_window_shrink_wrap (GimpImageWindow *window,
gtk_widget_get_window (widget)); gtk_widget_get_window (widget));
gdk_screen_get_monitor_workarea (screen, monitor, &rect); gdk_screen_get_monitor_workarea (screen, monitor, &rect);
gimp_display_shell_transform_bounds (active_shell, gimp_display_shell_scale_get_image_bounding_box (active_shell,
0, 0, NULL, NULL,
gimp_image_get_width (image),
gimp_image_get_height (image),
&x, &y,
&width, &height); &width, &height);
width = ceil (width - x);
height = ceil (height - y);
disp_width = active_shell->disp_width; disp_width = active_shell->disp_width;
disp_height = active_shell->disp_height; disp_height = active_shell->disp_height;
@ -1612,7 +1602,7 @@ gimp_image_window_shrink_wrap (GimpImageWindow *window,
* GimpDisplayShell::configure_event(). * GimpDisplayShell::configure_event().
*/ */
/* FIXME multiple shells */ /* FIXME multiple shells */
gimp_display_shell_scroll_center_image (active_shell, TRUE, TRUE); gimp_display_shell_scroll_center_content (active_shell, TRUE, TRUE);
} }
static GtkWidget * static GtkWidget *