Adding initial support for snapping layers/path_points by layers bounding boxes

This commit is contained in:
mr.fantastic 2023-03-08 19:08:55 +03:00 committed by Jehan
parent 54728e0fe1
commit 0aa8ac4660
14 changed files with 270 additions and 18 deletions

View File

@ -277,6 +277,13 @@ static const GimpToggleActionEntry view_toggle_actions[] =
FALSE,
GIMP_HELP_VIEW_SNAP_TO_VECTORS },
{ "view-snap-to-bbox", NULL,
NC_("view-action", "Snap to _Bounding Boxes"), NULL, { NULL },
NC_("view-action", "Tool operations snap to the bounding boxes"),
view_snap_to_bbox_cmd_callback,
FALSE,
GIMP_HELP_VIEW_SNAP_TO_BBOX },
{ "view-show-menubar", NULL,
NC_("view-action", "Show _Menubar"), NULL, { NULL },
NC_("view-action", "Show this window's menubar"),
@ -919,6 +926,8 @@ view_actions_update (GimpActionGroup *group,
SET_ACTIVE ("view-snap-to-canvas", display && options->snap_to_canvas);
SET_SENSITIVE ("view-snap-to-vectors", image);
SET_ACTIVE ("view-snap-to-vectors", display && options->snap_to_path);
SET_SENSITIVE ("view-snap-to-bbox", image);
SET_ACTIVE ("view-snap-to-bbox", display && options->snap_to_bbox);
SET_SENSITIVE ("view-padding-color-theme", image);
SET_SENSITIVE ("view-padding-color-light-check", image);

View File

@ -994,6 +994,23 @@ view_snap_to_vectors_cmd_callback (GimpAction *action,
}
}
void
view_snap_to_bbox_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpDisplayShell *shell;
gboolean active;
return_if_no_shell (shell, data);
active = g_variant_get_boolean (value);
if (active != gimp_display_shell_get_snap_to_bbox (shell))
{
gimp_display_shell_set_snap_to_bbox (shell, active);
}
}
void
view_padding_color_cmd_callback (GimpAction *action,
GVariant *value,

View File

@ -161,6 +161,9 @@ void view_snap_to_canvas_cmd_callback (GimpAction *action,
void view_snap_to_vectors_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data);
void view_snap_to_bbox_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data);
void view_padding_color_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data);

View File

@ -55,6 +55,7 @@ enum
PROP_SNAP_TO_GRID,
PROP_SNAP_TO_CANVAS,
PROP_SNAP_TO_PATH,
PROP_SNAP_TO_BBOX,
PROP_PADDING_MODE,
PROP_PADDING_COLOR,
PROP_PADDING_IN_SHOW_ALL
@ -206,6 +207,13 @@ gimp_display_options_class_init (GimpDisplayOptionsClass *klass)
FALSE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SNAP_TO_BBOX,
"snap-to-bbox",
"Snap to bounding boxes",
SNAP_TO_BBOX_BLURB,
FALSE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_ENUM (object_class, PROP_PADDING_MODE,
"padding-mode",
"Padding mode",
@ -338,6 +346,13 @@ gimp_display_options_fullscreen_class_init (GimpDisplayOptionsFullscreenClass *k
FALSE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SNAP_TO_BBOX,
"snap-to-bbox",
"Snap to bounding boxes",
SNAP_TO_BBOX_BLURB,
FALSE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_ENUM (object_class, PROP_PADDING_MODE,
"padding-mode",
"Padding mode",
@ -432,6 +447,13 @@ gimp_display_options_no_image_class_init (GimpDisplayOptionsNoImageClass *klass)
TRUE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SNAP_TO_BBOX,
"snap-to-bbox",
"Snap to bounding boxes",
SNAP_TO_BBOX_BLURB,
FALSE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SNAP_TO_GRID,
"snap-to-grid",
"Snap to grid",
@ -512,6 +534,9 @@ gimp_display_options_set_property (GObject *object,
case PROP_SNAP_TO_PATH:
options->snap_to_path = g_value_get_boolean (value);
break;
case PROP_SNAP_TO_BBOX:
options->snap_to_bbox = g_value_get_boolean (value);
break;
case PROP_PADDING_MODE:
options->padding_mode = g_value_get_enum (value);
break;
@ -580,6 +605,9 @@ gimp_display_options_get_property (GObject *object,
case PROP_SNAP_TO_PATH:
g_value_set_boolean (value, options->snap_to_path);
break;
case PROP_SNAP_TO_BBOX:
g_value_set_boolean (value, options->snap_to_bbox);
break;
case PROP_PADDING_MODE:
g_value_set_enum (value, options->padding_mode);
break;

View File

@ -57,6 +57,7 @@ struct _GimpDisplayOptions
gboolean snap_to_grid;
gboolean snap_to_canvas;
gboolean snap_to_path;
gboolean snap_to_bbox;
GimpCanvasPaddingMode padding_mode;
GimpRGB padding_color;

View File

@ -124,6 +124,9 @@ _("Snap to the canvas edges by default in new image windows.")
#define SNAP_TO_PATH_BLURB \
_("Snap to the active path by default in new image windows.")
#define SNAP_TO_BBOX_BLURB \
_("Snap to the layers bounding boxes by default in new image windows.")
#define DEFAULT_THRESHOLD_BLURB \
_("Tools such as fuzzy-select and bucket fill find regions based on a " \
"seed-fill algorithm. The seed fill starts at the initially selected " \

View File

@ -28,6 +28,7 @@
#include "gimpgrid.h"
#include "gimpguide.h"
#include "gimpimage.h"
#include "gimplayer.h"
#include "gimpimage-grid.h"
#include "gimpimage-guides.h"
#include "gimpimage-snap.h"
@ -55,7 +56,8 @@ gimp_image_snap_x (GimpImage *image,
gdouble epsilon_x,
gboolean snap_to_guides,
gboolean snap_to_grid,
gboolean snap_to_canvas)
gboolean snap_to_canvas,
gboolean snap_to_bbox)
{
gdouble mindist = G_MAXDOUBLE;
gboolean snapped = FALSE;
@ -68,7 +70,7 @@ gimp_image_snap_x (GimpImage *image,
if (! gimp_image_get_guides (image)) snap_to_guides = FALSE;
if (! gimp_image_get_grid (image)) snap_to_grid = FALSE;
if (! (snap_to_guides || snap_to_grid || snap_to_canvas))
if (! (snap_to_guides || snap_to_grid || snap_to_canvas || snap_to_bbox))
return FALSE;
if (x < -epsilon_x || x >= (gimp_image_get_width (image) + epsilon_x))
@ -126,6 +128,50 @@ gimp_image_snap_x (GimpImage *image,
&mindist, tx);
}
if (snap_to_bbox)
{
GList *layers_list = gimp_image_get_layer_list (image);
GList *selected_layers_list = gimp_image_get_selected_layers (image);
gdouble gcx;
gint gx, gy, gw, gh;
gboolean not_in_selected_set;
selected_layers_list = gimp_image_get_selected_layers (image);
layers_list = gimp_image_get_layer_list (image);
not_in_selected_set = TRUE;
for (GList *iter = layers_list; iter; iter = iter->next)
{
gimp_item_bounds (iter->data, &gx, &gy, &gw, &gh);
gimp_item_get_offset (iter->data, &gx, &gy);
gcx = (double) gx + (double) gw/2.0;
not_in_selected_set = TRUE;
for (GList *iter2 = selected_layers_list; iter2; iter2 = iter2->next)
{
if (iter2->data == iter->data)
not_in_selected_set = FALSE;
}
if ((gint) x >= gx && (gint) x <= (gx+gw) && not_in_selected_set)
{
snapped |= gimp_image_snap_distance (x, (double) gx,
epsilon_x,
&mindist, tx);
snapped |= gimp_image_snap_distance (x, (double) gx+gw,
epsilon_x,
&mindist, tx);
snapped |= gimp_image_snap_distance (x, gcx,
epsilon_x,
&mindist, tx);
}
}
g_list_free (layers_list);
}
return snapped;
}
@ -136,7 +182,8 @@ gimp_image_snap_y (GimpImage *image,
gdouble epsilon_y,
gboolean snap_to_guides,
gboolean snap_to_grid,
gboolean snap_to_canvas)
gboolean snap_to_canvas,
gboolean snap_to_bbox)
{
gdouble mindist = G_MAXDOUBLE;
gboolean snapped = FALSE;
@ -149,7 +196,7 @@ gimp_image_snap_y (GimpImage *image,
if (! gimp_image_get_guides (image)) snap_to_guides = FALSE;
if (! gimp_image_get_grid (image)) snap_to_grid = FALSE;
if (! (snap_to_guides || snap_to_grid || snap_to_canvas))
if (! (snap_to_guides || snap_to_grid || snap_to_canvas || snap_to_bbox))
return FALSE;
if (y < -epsilon_y || y >= (gimp_image_get_height (image) + epsilon_y))
@ -207,6 +254,50 @@ gimp_image_snap_y (GimpImage *image,
&mindist, ty);
}
if (snap_to_bbox)
{
GList *selected_layers_list;
GList *layers_list;
gdouble gcy;
gint gx, gy, gw, gh;
gboolean not_in_selected_set;
selected_layers_list = gimp_image_get_selected_layers (image);
layers_list = gimp_image_get_layer_list (image);
not_in_selected_set = TRUE;
for (GList *iter = layers_list; iter; iter = iter->next)
{
gimp_item_bounds (iter->data, &gx, &gy, &gw, &gh);
gimp_item_get_offset (iter->data, &gx, &gy);
gcy = (double) gy + (double) gh/2.0;
not_in_selected_set = TRUE;
for (GList *iter2 = selected_layers_list; iter2; iter2 = iter2->next)
{
if (iter2->data == iter->data)
not_in_selected_set = FALSE;
}
if ((gint) y >= gy && (gint) y <= (gy+gh) && not_in_selected_set)
{
snapped |= gimp_image_snap_distance (y, (double) gy,
epsilon_y,
&mindist, ty);
snapped |= gimp_image_snap_distance (y, (double) gy+gh,
epsilon_y,
&mindist, ty);
snapped |= gimp_image_snap_distance (y, gcy,
epsilon_y,
&mindist, ty);
}
}
g_list_free (layers_list);
}
return snapped;
}
@ -222,6 +313,7 @@ gimp_image_snap_point (GimpImage *image,
gboolean snap_to_grid,
gboolean snap_to_canvas,
gboolean snap_to_vectors,
gboolean snap_to_bbox,
gboolean show_all)
{
gdouble mindist_x = G_MAXDOUBLE;
@ -242,7 +334,7 @@ gimp_image_snap_point (GimpImage *image,
if (! gimp_image_get_selected_vectors (image))
snap_to_vectors = FALSE;
if (! (snap_to_guides || snap_to_grid || snap_to_canvas || snap_to_vectors))
if (! (snap_to_guides || snap_to_grid || snap_to_canvas || snap_to_vectors || snap_to_bbox))
return FALSE;
if (! show_all &&
@ -370,6 +462,55 @@ gimp_image_snap_point (GimpImage *image,
}
}
if (snap_to_bbox)
{
GList *layers_list = gimp_image_get_layer_list (image);
for (GList *iter = layers_list; iter; iter = iter->next)
{
gdouble gcx;
gdouble gcy;
gint gx, gy, gw, gh;
gimp_item_bounds (iter->data, &gx, &gy, &gw, &gh);
gimp_item_get_offset (iter->data, &gx, &gy);
gcx = (double) gx + (double) gw/2.0;
gcy = (double) gy + (double) gh/2.0;
if ((gint) x >= gx && (gint) x <= (gx+gw))
{
snapped |= gimp_image_snap_distance (x, (double) gx,
epsilon_x,
&mindist_x, tx);
snapped |= gimp_image_snap_distance (x, (double) gx+gw,
epsilon_x,
&mindist_x, tx);
snapped |= gimp_image_snap_distance (x, gcx,
epsilon_x,
&mindist_x, tx);
}
if ((gint) y >= gy && (gint) y <= (gy+gh))
{
snapped |= gimp_image_snap_distance (y, (double) gy,
epsilon_y,
&mindist_y, ty);
snapped |= gimp_image_snap_distance (y, (double) gy+gh,
epsilon_y,
&mindist_y, ty);
snapped |= gimp_image_snap_distance (y, gcy,
epsilon_y,
&mindist_y, ty);
}
}
g_list_free (layers_list);
}
return snapped;
}
@ -386,7 +527,8 @@ gimp_image_snap_rectangle (GimpImage *image,
gboolean snap_to_guides,
gboolean snap_to_grid,
gboolean snap_to_canvas,
gboolean snap_to_vectors)
gboolean snap_to_vectors,
gboolean snap_to_bbox)
{
gdouble nx, ny;
gdouble mindist_x = G_MAXDOUBLE;
@ -409,7 +551,7 @@ gimp_image_snap_rectangle (GimpImage *image,
if (! gimp_image_get_selected_vectors (image))
snap_to_vectors = FALSE;
if (! (snap_to_guides || snap_to_grid || snap_to_canvas || snap_to_vectors))
if (! (snap_to_guides || snap_to_grid || snap_to_canvas || snap_to_vectors || snap_to_bbox))
return FALSE;
/* left edge */
@ -417,7 +559,8 @@ gimp_image_snap_rectangle (GimpImage *image,
MIN (epsilon_x, mindist_x),
snap_to_guides,
snap_to_grid,
snap_to_canvas))
snap_to_canvas,
snap_to_bbox))
{
mindist_x = ABS (nx - x1);
*tx1 = nx;
@ -429,7 +572,8 @@ gimp_image_snap_rectangle (GimpImage *image,
MIN (epsilon_x, mindist_x),
snap_to_guides,
snap_to_grid,
snap_to_canvas))
snap_to_canvas,
snap_to_bbox))
{
mindist_x = ABS (nx - x2);
*tx1 = RINT (x1 + (nx - x2));
@ -441,7 +585,8 @@ gimp_image_snap_rectangle (GimpImage *image,
MIN (epsilon_x, mindist_x),
snap_to_guides,
snap_to_grid,
snap_to_canvas))
snap_to_canvas,
snap_to_bbox))
{
mindist_x = ABS (nx - x_center);
*tx1 = RINT (x1 + (nx - x_center));
@ -453,7 +598,8 @@ gimp_image_snap_rectangle (GimpImage *image,
MIN (epsilon_y, mindist_y),
snap_to_guides,
snap_to_grid,
snap_to_canvas))
snap_to_canvas,
snap_to_bbox))
{
mindist_y = ABS (ny - y1);
*ty1 = ny;
@ -465,7 +611,8 @@ gimp_image_snap_rectangle (GimpImage *image,
MIN (epsilon_y, mindist_y),
snap_to_guides,
snap_to_grid,
snap_to_canvas))
snap_to_canvas,
snap_to_bbox))
{
mindist_y = ABS (ny - y2);
*ty1 = RINT (y1 + (ny - y2));
@ -477,7 +624,8 @@ gimp_image_snap_rectangle (GimpImage *image,
MIN (epsilon_y, mindist_y),
snap_to_guides,
snap_to_grid,
snap_to_canvas))
snap_to_canvas,
snap_to_bbox))
{
mindist_y = ABS (ny - y_center);
*ty1 = RINT (y1 + (ny - y_center));

View File

@ -25,14 +25,16 @@ gboolean gimp_image_snap_x (GimpImage *image,
gdouble epsilon_x,
gboolean snap_to_guides,
gboolean snap_to_grid,
gboolean snap_to_canvas);
gboolean snap_to_canvas,
gboolean snap_to_bbox);
gboolean gimp_image_snap_y (GimpImage *image,
gdouble y,
gdouble *ty,
gdouble epsilon_y,
gboolean snap_to_guides,
gboolean snap_to_grid,
gboolean snap_to_canvas);
gboolean snap_to_canvas,
gboolean snap_to_bbox);
gboolean gimp_image_snap_point (GimpImage *image,
gdouble x,
gdouble y,
@ -44,6 +46,7 @@ gboolean gimp_image_snap_point (GimpImage *image,
gboolean snap_to_grid,
gboolean snap_to_canvas,
gboolean snap_to_vectors,
gboolean snap_to_bbox,
gboolean show_all);
gboolean gimp_image_snap_rectangle (GimpImage *image,
gdouble x1,
@ -57,7 +60,8 @@ gboolean gimp_image_snap_rectangle (GimpImage *image,
gboolean snap_to_guides,
gboolean snap_to_grid,
gboolean snap_to_canvas,
gboolean snap_to_vectors);
gboolean snap_to_vectors,
gboolean snap_to_bbox);
#endif /* __GIMP_IMAGE_SNAP_H__ */

View File

@ -1140,6 +1140,9 @@ prefs_behavior_options_frame_add (Gimp *gimp,
prefs_check_button_add (object, "snap-to-path",
_("Snap to _Active Path"),
GTK_BOX (checks_vbox));
prefs_check_button_add (object, "snap-to-bbox",
_("Snap to _Bounding Box"),
GTK_BOX (checks_vbox));
}
static void

View File

@ -465,6 +465,27 @@ gimp_display_shell_get_snap_to_vectors (GimpDisplayShell *shell)
return appearance_get_options (shell)->snap_to_path;
}
void
gimp_display_shell_set_snap_to_bbox (GimpDisplayShell *shell,
gboolean snap)
{
GimpDisplayOptions *options;
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
options = appearance_get_options (shell);
g_object_set (options, "snap-to-bbox", snap, NULL);
}
gboolean
gimp_display_shell_get_snap_to_bbox (GimpDisplayShell *shell)
{
g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE);
return appearance_get_options (shell)->snap_to_bbox;
}
void
gimp_display_shell_set_padding (GimpDisplayShell *shell,
GimpCanvasPaddingMode padding_mode,

View File

@ -78,6 +78,10 @@ void gimp_display_shell_set_snap_to_vectors (GimpDisplayShell *s
gboolean snap);
gboolean gimp_display_shell_get_snap_to_vectors (GimpDisplayShell *shell);
void gimp_display_shell_set_snap_to_bbox (GimpDisplayShell *shell,
gboolean snap);
gboolean gimp_display_shell_get_snap_to_bbox (GimpDisplayShell *shell);
void gimp_display_shell_set_padding (GimpDisplayShell *shell,
GimpCanvasPaddingMode mode,
const GimpRGB *color);

View File

@ -1649,6 +1649,7 @@ gimp_display_shell_snap_coords (GimpDisplayShell *shell,
gboolean snap_to_grid = FALSE;
gboolean snap_to_canvas = FALSE;
gboolean snap_to_vectors = FALSE;
gboolean snap_to_bbox = FALSE;
gboolean snapped = FALSE;
g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE);
@ -1676,7 +1677,12 @@ gimp_display_shell_snap_coords (GimpDisplayShell *shell,
snap_to_vectors = TRUE;
}
if (snap_to_guides || snap_to_grid || snap_to_canvas || snap_to_vectors)
if (gimp_display_shell_get_snap_to_bbox (shell))
{
snap_to_bbox = TRUE;
}
if (snap_to_guides || snap_to_grid || snap_to_canvas || snap_to_vectors || snap_to_bbox)
{
gint snap_distance;
gdouble tx, ty;
@ -1699,7 +1705,8 @@ gimp_display_shell_snap_coords (GimpDisplayShell *shell,
snap_to_guides,
snap_to_grid,
snap_to_canvas,
snap_to_vectors);
snap_to_vectors,
snap_to_bbox);
}
else
{
@ -1714,6 +1721,7 @@ gimp_display_shell_snap_coords (GimpDisplayShell *shell,
snap_to_grid,
snap_to_canvas,
snap_to_vectors,
snap_to_bbox,
shell->show_all);
}

View File

@ -114,6 +114,7 @@
#define GIMP_HELP_VIEW_SNAP_TO_GRID "gimp-view-snap-to-grid"
#define GIMP_HELP_VIEW_SNAP_TO_CANVAS "gimp-view-snap-to-canvas"
#define GIMP_HELP_VIEW_SNAP_TO_VECTORS "gimp-view-snap-to-vectors"
#define GIMP_HELP_VIEW_SNAP_TO_BBOX "gimp-view-snap-to-bbox"
#define GIMP_HELP_VIEW_SHOW_MENUBAR "gimp-view-show-menubar"
#define GIMP_HELP_VIEW_SHOW_RULERS "gimp-view-show-rulers"
#define GIMP_HELP_VIEW_SHOW_SCROLLBARS "gimp-view-show-scrollbars"

View File

@ -264,6 +264,8 @@
<item><attribute name="action">app.view-snap-to-grid</attribute></item>
<item><attribute name="action">app.view-snap-to-canvas</attribute></item>
<item><attribute name="action">app.view-snap-to-vectors</attribute></item>
<item><attribute name="action">app.view-snap-to-bbox</attribute></item>
<item><attribute name="action">app.view-snap-to-equidistance</attribute></item>
</section>
<section>
<submenu>