tools: prevent on-canvas text editor from being dragged outside the image bounds
This commit prevents the on-canvas text editor from being dragged outside the image bounds by checking the overlay's position and adjusting the coordinates to keep it within the canvas. Additionally, it checks whether the overlay is entirely outside the canvas and, if so, pushes it back inside.
This commit is contained in:
parent
791f9616fe
commit
f089ed69d7
5 changed files with 238 additions and 4 deletions
|
|
@ -195,6 +195,11 @@ static void gimp_display_shell_transform_overlay (GimpDisplayShell *shell,
|
|||
static gboolean gimp_display_shell_draw (GimpDisplayShell *shell,
|
||||
cairo_t *cr,
|
||||
gpointer *data);
|
||||
static void gimp_display_shell_push_overlay_inside_canvas
|
||||
(GimpDisplayShell *shell,
|
||||
GtkWidget *child,
|
||||
gdouble *limits,
|
||||
gdouble *corners);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GimpDisplayShell, gimp_display_shell,
|
||||
|
|
@ -1276,12 +1281,39 @@ gimp_display_shell_overlay_allocate (GtkWidget *child,
|
|||
GtkAllocation *allocation,
|
||||
GimpDisplayShellOverlay *overlay)
|
||||
{
|
||||
gdouble x, y;
|
||||
gdouble tlx, tly, brx, bry;
|
||||
gdouble llimit, rlimit, ulimit, blimit;
|
||||
|
||||
gimp_display_shell_transform_overlay (overlay->shell, child, &x, &y);
|
||||
gimp_ruler_get_range ((GimpRuler *) overlay->shell->hrule,
|
||||
&llimit, &rlimit, NULL);
|
||||
gimp_ruler_get_range ((GimpRuler *) overlay->shell->vrule,
|
||||
&ulimit, &blimit, NULL);
|
||||
|
||||
gimp_overlay_box_set_child_position (GIMP_OVERLAY_BOX (overlay->shell->canvas),
|
||||
child, x, y);
|
||||
gimp_display_shell_get_overlay_corners (overlay->shell,
|
||||
child,
|
||||
overlay->image_x, overlay->image_y,
|
||||
&tlx, &tly,
|
||||
&brx, &bry);
|
||||
|
||||
/* If the overlay is entirely outside the canvas, we push it inside the canvas */
|
||||
if (tlx > rlimit ||
|
||||
tly > blimit ||
|
||||
brx < llimit ||
|
||||
bry < ulimit)
|
||||
{
|
||||
gimp_display_shell_push_overlay_inside_canvas (overlay->shell,
|
||||
child,
|
||||
(gdouble[]) {ulimit, rlimit, blimit, llimit},
|
||||
(gdouble[]) {tlx, tly, brx, bry});
|
||||
}
|
||||
else
|
||||
{
|
||||
gdouble x, y;
|
||||
|
||||
gimp_display_shell_transform_overlay (overlay->shell, child, &x, &y);
|
||||
gimp_overlay_box_set_child_position (GIMP_OVERLAY_BOX (overlay->shell->canvas),
|
||||
child, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1386,6 +1418,62 @@ gimp_display_shell_draw (GimpDisplayShell *shell,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_display_shell_push_overlay_inside_canvas (GimpDisplayShell *shell,
|
||||
GtkWidget *child,
|
||||
gdouble *limits,
|
||||
gdouble *corners)
|
||||
{
|
||||
gdouble ulimit, rlimit, blimit, llimit;
|
||||
gdouble tlx, tly, brx, bry;
|
||||
|
||||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||||
g_return_if_fail (GTK_IS_WIDGET (shell));
|
||||
|
||||
ulimit = limits[0];
|
||||
rlimit = limits[1];
|
||||
blimit = limits[2];
|
||||
llimit = limits[3];
|
||||
|
||||
tlx = corners[0];
|
||||
tly = corners[1];
|
||||
brx = corners[2];
|
||||
bry = corners[3];
|
||||
|
||||
if (brx < llimit)
|
||||
{
|
||||
gimp_display_shell_move_overlay (shell,
|
||||
child,
|
||||
llimit, tly,
|
||||
GIMP_HANDLE_ANCHOR_NORTH_WEST,
|
||||
0, 0);
|
||||
}
|
||||
if (bry < ulimit)
|
||||
{
|
||||
gimp_display_shell_move_overlay (shell,
|
||||
child,
|
||||
tlx, ulimit,
|
||||
GIMP_HANDLE_ANCHOR_NORTH_WEST,
|
||||
0, 0);
|
||||
}
|
||||
if (tlx > rlimit)
|
||||
{
|
||||
gimp_display_shell_move_overlay (shell,
|
||||
child,
|
||||
rlimit, bry,
|
||||
GIMP_HANDLE_ANCHOR_SOUTH_EAST,
|
||||
0, 0);
|
||||
}
|
||||
if (tly > blimit)
|
||||
{
|
||||
gimp_display_shell_move_overlay (shell,
|
||||
child,
|
||||
brx, blimit,
|
||||
GIMP_HANDLE_ANCHOR_SOUTH_EAST,
|
||||
0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* public functions */
|
||||
|
||||
GtkWidget *
|
||||
|
|
@ -2340,3 +2428,96 @@ gimp_display_shell_is_drawn (GimpDisplayShell *shell)
|
|||
{
|
||||
return shell->drawn;
|
||||
}
|
||||
|
||||
/**
|
||||
* gimp_display_shell_get_overlay_corners:
|
||||
* @shell: a #GimpDisplayShell
|
||||
* @child: a child widget of the shell
|
||||
* @image_x: the x coordinate in image coordinates
|
||||
* @image_y: the y coordinate in image coordinates
|
||||
* @top_left_x: return location for the top left x coordinate in image coordinates
|
||||
* @top_left_y: return location for the top left y coordinate in image coordinates
|
||||
* @bottom_right_x: return location for the bottom right x coordinate in image coordinates
|
||||
* @bottom_right_y: return location for the bottom right y coordinate in image coordinates
|
||||
*
|
||||
* This function calculates the corners of an overlay widget in image coordinates.
|
||||
**/
|
||||
void
|
||||
gimp_display_shell_get_overlay_corners (GimpDisplayShell *shell,
|
||||
GtkWidget *child,
|
||||
gdouble image_x,
|
||||
gdouble image_y,
|
||||
gdouble *top_left_x,
|
||||
gdouble *top_left_y,
|
||||
gdouble *bottom_right_x,
|
||||
gdouble *bottom_right_y)
|
||||
{
|
||||
GimpDisplayShellOverlay *overlay;
|
||||
GtkRequisition req;
|
||||
gdouble tl_disp_x, tl_disp_y;
|
||||
gdouble br_disp_x, br_disp_y;
|
||||
|
||||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||||
|
||||
overlay = g_object_get_data (G_OBJECT (child), "image-coords-overlay");
|
||||
|
||||
gimp_display_shell_transform_xy_f (shell,
|
||||
image_x, image_y,
|
||||
&tl_disp_x, &tl_disp_y);
|
||||
|
||||
gtk_widget_get_preferred_size (child, &req, NULL);
|
||||
|
||||
switch (overlay->anchor)
|
||||
{
|
||||
case GIMP_HANDLE_ANCHOR_CENTER:
|
||||
tl_disp_x -= req.width / 2;
|
||||
tl_disp_y -= req.height / 2;
|
||||
break;
|
||||
case GIMP_HANDLE_ANCHOR_NORTH:
|
||||
tl_disp_x -= req.width / 2;
|
||||
tl_disp_y += overlay->spacing_y;
|
||||
break;
|
||||
case GIMP_HANDLE_ANCHOR_NORTH_WEST:
|
||||
tl_disp_x += overlay->spacing_x;
|
||||
tl_disp_y += overlay->spacing_y;
|
||||
break;
|
||||
case GIMP_HANDLE_ANCHOR_NORTH_EAST:
|
||||
tl_disp_x -= req.width + overlay->spacing_x;
|
||||
tl_disp_y += overlay->spacing_y;
|
||||
break;
|
||||
case GIMP_HANDLE_ANCHOR_SOUTH:
|
||||
tl_disp_x -= req.width / 2;
|
||||
tl_disp_y -= req.height + overlay->spacing_y;
|
||||
break;
|
||||
case GIMP_HANDLE_ANCHOR_SOUTH_WEST:
|
||||
tl_disp_x += overlay->spacing_x;
|
||||
tl_disp_y -= req.height + overlay->spacing_y;
|
||||
break;
|
||||
case GIMP_HANDLE_ANCHOR_SOUTH_EAST:
|
||||
tl_disp_x -= req.width + overlay->spacing_x;
|
||||
tl_disp_y -= req.height + overlay->spacing_y;
|
||||
break;
|
||||
case GIMP_HANDLE_ANCHOR_WEST:
|
||||
tl_disp_x += overlay->spacing_x;
|
||||
tl_disp_y -= req.height / 2;
|
||||
break;
|
||||
case GIMP_HANDLE_ANCHOR_EAST:
|
||||
tl_disp_x -= req.width + overlay->spacing_x;
|
||||
tl_disp_y -= req.height / 2;
|
||||
break;
|
||||
default:
|
||||
tl_disp_x -= overlay->spacing_x;
|
||||
tl_disp_y -= overlay->spacing_y;
|
||||
break;
|
||||
}
|
||||
|
||||
br_disp_x = tl_disp_x + req.width;
|
||||
br_disp_y = tl_disp_y + req.height;
|
||||
|
||||
gimp_display_shell_untransform_xy_f (shell,
|
||||
tl_disp_x, tl_disp_y,
|
||||
top_left_x, top_left_y);
|
||||
gimp_display_shell_untransform_xy_f (shell,
|
||||
br_disp_x, br_disp_y,
|
||||
bottom_right_x, bottom_right_y);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -363,3 +363,13 @@ void gimp_display_shell_set_mask (GimpDisplayShell *shell,
|
|||
gboolean inverted);
|
||||
|
||||
gboolean gimp_display_shell_is_drawn (GimpDisplayShell *shell);
|
||||
|
||||
void gimp_display_shell_get_overlay_corners
|
||||
(GimpDisplayShell *shell,
|
||||
GtkWidget *child,
|
||||
gdouble image_x,
|
||||
gdouble image_y,
|
||||
gdouble *top_left_x,
|
||||
gdouble *top_left_y,
|
||||
gdouble *bottom_right_x,
|
||||
gdouble *bottom_right_y);
|
||||
|
|
|
|||
|
|
@ -617,6 +617,18 @@ gimp_text_layer_get_style_overlay_position (GimpTextLayer *layer,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gimp_text_layer_is_style_overlay_positioned (GimpTextLayer *layer)
|
||||
{
|
||||
GimpTextLayerPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GIMP_IS_TEXT_LAYER (layer), FALSE);
|
||||
|
||||
priv = layer->private;
|
||||
|
||||
return priv->style_overlay_positioned;
|
||||
}
|
||||
|
||||
void
|
||||
gimp_text_layer_set_style_overlay_offset (GimpTextLayer *layer,
|
||||
gdouble offset_x,
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ gboolean gimp_text_layer_get_style_overlay_position
|
|||
(GimpTextLayer *layer,
|
||||
gdouble *x,
|
||||
gdouble *y);
|
||||
gboolean gimp_text_layer_is_style_overlay_positioned
|
||||
(GimpTextLayer *layer);
|
||||
void gimp_text_layer_set_style_overlay_offset
|
||||
(GimpTextLayer *layer,
|
||||
gdouble offset_x,
|
||||
|
|
|
|||
|
|
@ -2076,6 +2076,8 @@ gimp_text_tool_style_overlay_button_motion (GtkWidget *widget,
|
|||
GimpTool *tool = GIMP_TOOL (text_tool);
|
||||
GimpDisplayShell *shell = gimp_display_get_shell (tool->display);
|
||||
GimpTextStyleEditor *style_editor;
|
||||
gdouble llimit, rlimit, ulimit, blimit;
|
||||
gdouble tlx, tly, brx, bry;
|
||||
gdouble x, y;
|
||||
gdouble x_off, y_off;
|
||||
|
||||
|
|
@ -2089,6 +2091,33 @@ gimp_text_tool_style_overlay_button_motion (GtkWidget *widget,
|
|||
x, y,
|
||||
&x, &y);
|
||||
|
||||
gimp_ruler_get_range ((GimpRuler *) shell->hrule,
|
||||
&llimit, &rlimit, NULL);
|
||||
gimp_ruler_get_range ((GimpRuler *) shell->vrule,
|
||||
&ulimit, &blimit, NULL);
|
||||
|
||||
gimp_display_shell_get_overlay_corners (shell, text_tool->style_overlay,
|
||||
x, y,
|
||||
&tlx, &tly,
|
||||
&brx, &bry);
|
||||
|
||||
/* If the overlay is being dragged, we need to check if it is still
|
||||
* within the image bounds. If it is not, we adjust the coordinates.
|
||||
* This is to prevent the overlay from being dragged outside the image
|
||||
* bounds, which would cause it to be lost.
|
||||
*/
|
||||
if (gimp_text_layer_is_style_overlay_positioned (text_tool->layer))
|
||||
{
|
||||
if (tlx < llimit)
|
||||
x += (llimit - tlx);
|
||||
if (tly < ulimit)
|
||||
y += (ulimit - tly);
|
||||
if (brx > rlimit)
|
||||
x -= (brx - rlimit);
|
||||
if (bry > blimit)
|
||||
y -= (bry - blimit);
|
||||
}
|
||||
|
||||
gimp_display_shell_move_overlay (shell,
|
||||
text_tool->style_overlay,
|
||||
x, y, -1,
|
||||
|
|
|
|||
Loading…
Reference in a new issue