From e48b002c8474f9bf30da4277615d33928d19cd51 Mon Sep 17 00:00:00 2001 From: Jehan Date: Tue, 8 Nov 2022 23:18:42 +0100 Subject: [PATCH] app, icons, libgimpwidgets: add "distribute with evenly gaps" options. There was one case in Inkscape which we could not do: distributing objects keeping even gaps between them. Until now, we could only distribute keeping even distance between anchor points (top, left, bottom, right or center). With these 2 additional distribute options, I believe that GIMP is able to do all the Alignment and Distribution options available in Inkscape (not the "Rearrange" or node features, neither the text align/distrib; I just mean the common align/distribute on objects), and even a bit more thanks to the anchor point system (e.g. in Inkscape, we can't left or right-align to a reference object/image center, or we can't center to a reference left/right/bottom/top border; but we can do it in GIMP). The icons are hopefully temporary, until we can make better ones. --- app/core/core-enums.c | 20 +- app/core/core-enums.h | 18 +- app/core/gimpimage-arrange.c | 68 +++++- app/tools/gimpalignoptions.c | 24 ++- app/tools/gimpaligntool.c | 2 + icons/Color/icon-list.mk | 4 + .../scalable/gimp-even-horizontal-gap.svg | 134 ++++++++++++ .../Color/scalable/gimp-even-vertical-gap.svg | 135 ++++++++++++ icons/Symbolic/icon-list.mk | 4 + .../gimp-even-horizontal-gap-symbolic.svg | 195 +++++++++++++++++ .../gimp-even-vertical-gap-symbolic.svg | 196 ++++++++++++++++++ icons/icon-lists/bitmap_24.list | 2 + icons/icon-lists/scalable.list | 2 + libgimpwidgets/gimpicons.h | 3 + 14 files changed, 781 insertions(+), 26 deletions(-) create mode 100644 icons/Color/scalable/gimp-even-horizontal-gap.svg create mode 100644 icons/Color/scalable/gimp-even-vertical-gap.svg create mode 100644 icons/Symbolic/scalable/gimp-even-horizontal-gap-symbolic.svg create mode 100644 icons/Symbolic/scalable/gimp-even-vertical-gap-symbolic.svg diff --git a/app/core/core-enums.c b/app/core/core-enums.c index 8cf50508b4..a9353265a3 100644 --- a/app/core/core-enums.c +++ b/app/core/core-enums.c @@ -53,19 +53,23 @@ gimp_alignment_type_get_type (void) { GIMP_ALIGN_BOTTOM, "GIMP_ALIGN_BOTTOM", "align-bottom" }, { GIMP_ARRANGE_HFILL, "GIMP_ARRANGE_HFILL", "arrange-hfill" }, { GIMP_ARRANGE_VFILL, "GIMP_ARRANGE_VFILL", "arrange-vfill" }, + { GIMP_DISTRIBUTE_EVEN_HORIZONTAL_GAP, "GIMP_DISTRIBUTE_EVEN_HORIZONTAL_GAP", "distribute-even-horizontal-gap" }, + { GIMP_DISTRIBUTE_EVEN_VERTICAL_GAP, "GIMP_DISTRIBUTE_EVEN_VERTICAL_GAP", "distribute-even-vertical-gap" }, { 0, NULL, NULL } }; static const GimpEnumDesc descs[] = { - { GIMP_ALIGN_LEFT, "GIMP_ALIGN_LEFT", NULL }, - { GIMP_ALIGN_HCENTER, "GIMP_ALIGN_HCENTER", NULL }, - { GIMP_ALIGN_RIGHT, "GIMP_ALIGN_RIGHT", NULL }, - { GIMP_ALIGN_TOP, "GIMP_ALIGN_TOP", NULL }, - { GIMP_ALIGN_VCENTER, "GIMP_ALIGN_VCENTER", NULL }, - { GIMP_ALIGN_BOTTOM, "GIMP_ALIGN_BOTTOM", NULL }, - { GIMP_ARRANGE_HFILL, "GIMP_ARRANGE_HFILL", NULL }, - { GIMP_ARRANGE_VFILL, "GIMP_ARRANGE_VFILL", NULL }, + { GIMP_ALIGN_LEFT, NC_("alignment-type", "Align to the left"), NULL }, + { GIMP_ALIGN_HCENTER, NC_("alignment-type", "Center horizontally"), NULL }, + { GIMP_ALIGN_RIGHT, NC_("alignment-type", "Align to the right"), NULL }, + { GIMP_ALIGN_TOP, NC_("alignment-type", "Align to the top"), NULL }, + { GIMP_ALIGN_VCENTER, NC_("alignment-type", "Center vertically"), NULL }, + { GIMP_ALIGN_BOTTOM, NC_("alignment-type", "Align to the bottom"), NULL }, + { GIMP_ARRANGE_HFILL, NC_("alignment-type", "Distribute anchor points horizontally evenly"), NULL }, + { GIMP_ARRANGE_VFILL, NC_("alignment-type", "Distribute anchor points vertically evenly"), NULL }, + { GIMP_DISTRIBUTE_EVEN_HORIZONTAL_GAP, NC_("alignment-type", "Distribute horizontally with even horizontal gaps"), NULL }, + { GIMP_DISTRIBUTE_EVEN_VERTICAL_GAP, NC_("alignment-type", "Distribute vertically with even vertical gaps"), NULL }, { 0, NULL, NULL } }; diff --git a/app/core/core-enums.h b/app/core/core-enums.h index f4997a252a..a33596d337 100644 --- a/app/core/core-enums.h +++ b/app/core/core-enums.h @@ -54,14 +54,16 @@ GType gimp_alignment_type_get_type (void) G_GNUC_CONST; typedef enum /*< pdb-skip >*/ { - GIMP_ALIGN_LEFT, - GIMP_ALIGN_HCENTER, - GIMP_ALIGN_RIGHT, - GIMP_ALIGN_TOP, - GIMP_ALIGN_VCENTER, - GIMP_ALIGN_BOTTOM, - GIMP_ARRANGE_HFILL, - GIMP_ARRANGE_VFILL + GIMP_ALIGN_LEFT, /*< desc="Align to the left" >*/ + GIMP_ALIGN_HCENTER, /*< desc="Center horizontally" >*/ + GIMP_ALIGN_RIGHT, /*< desc="Align to the right" >*/ + GIMP_ALIGN_TOP, /*< desc="Align to the top" >*/ + GIMP_ALIGN_VCENTER, /*< desc="Center vertically" >*/ + GIMP_ALIGN_BOTTOM, /*< desc="Align to the bottom" >*/ + GIMP_ARRANGE_HFILL, /*< desc="Distribute anchor points horizontally evenly" >*/ + GIMP_ARRANGE_VFILL, /*< desc="Distribute anchor points vertically evenly" >*/ + GIMP_DISTRIBUTE_EVEN_HORIZONTAL_GAP, /*< desc="Distribute horizontally with even horizontal gaps" >*/ + GIMP_DISTRIBUTE_EVEN_VERTICAL_GAP, /*< desc="Distribute vertically with even vertical gaps" >*/ } GimpAlignmentType; diff --git a/app/core/gimpimage-arrange.c b/app/core/gimpimage-arrange.c index 442dd29ad0..76a4f46c40 100644 --- a/app/core/gimpimage-arrange.c +++ b/app/core/gimpimage-arrange.c @@ -155,6 +155,20 @@ gimp_image_arrange_objects (GimpImage *image, do_y = TRUE; break; + case GIMP_DISTRIBUTE_EVEN_HORIZONTAL_GAP: + use_obj_x_offset = TRUE; + do_x = TRUE; + case GIMP_DISTRIBUTE_EVEN_VERTICAL_GAP: + if (GIMP_IS_GUIDE (reference) || g_list_length (list) <= 2) + return; + + if (! do_x) + do_y = TRUE; + + /* Gap distribution does not use the anchor point. */ + align_x = align_y = 0.0; + break; + default: g_return_if_reached (); } @@ -171,22 +185,46 @@ gimp_image_arrange_objects (GimpImage *image, { GList *list; gint n; - gint distr_length = 0; - gdouble fill_offset = 0; + gdouble fill_offset = 0; - if (reference_alignment == GIMP_ARRANGE_HFILL || - reference_alignment == GIMP_ARRANGE_VFILL) + if (reference_alignment == GIMP_ARRANGE_HFILL || + reference_alignment == GIMP_ARRANGE_VFILL || + reference_alignment == GIMP_DISTRIBUTE_EVEN_HORIZONTAL_GAP || + reference_alignment == GIMP_DISTRIBUTE_EVEN_VERTICAL_GAP) { /* Distribution does not use the reference. Extreme coordinate items * are used instead. */ GList *last_object = g_list_last (object_list); + gint distr_length; z0 = GPOINTER_TO_INT (g_object_get_data (object_list->data, "align-offset")); distr_length = GPOINTER_TO_INT (g_object_get_data (last_object->data, "align-offset")) - z0; - /* The offset parameter works as an internal margin */ - fill_offset = (distr_length - 2 * offset) / (gdouble) (g_list_length (object_list) - 1); + if (reference_alignment == GIMP_DISTRIBUTE_EVEN_HORIZONTAL_GAP || + reference_alignment == GIMP_DISTRIBUTE_EVEN_VERTICAL_GAP) + { + for (list = object_list; list && list->next; list = g_list_next (list)) + { + gint obj_len; + + if (reference_alignment == GIMP_DISTRIBUTE_EVEN_HORIZONTAL_GAP) + obj_len = GPOINTER_TO_INT (g_object_get_data (list->data, "align-width")); + else + obj_len = GPOINTER_TO_INT (g_object_get_data (list->data, "align-height")); + distr_length -= obj_len; + + /* Initial offset is at end of first object. */ + if (list == object_list) + z0 += obj_len; + } + fill_offset = distr_length / (gdouble) (g_list_length (object_list) - 1); + } + else + { + /* The offset parameter works as an internal margin */ + fill_offset = (distr_length - 2 * offset) / (gdouble) (g_list_length (object_list) - 1); + } /* Removing first and last objects. These stay unmoved. */ object_list = g_list_delete_link (object_list, last_object); @@ -228,6 +266,24 @@ gimp_image_arrange_objects (GimpImage *image, { ytranslate = ROUND (z0 - z1 + n * fill_offset); } + else if (reference_alignment == GIMP_DISTRIBUTE_EVEN_HORIZONTAL_GAP) + { + gint obj_len; + + xtranslate = ROUND (z0 + fill_offset - z1); + + obj_len = GPOINTER_TO_INT (g_object_get_data (target, "align-width")); + z0 = z0 + fill_offset + obj_len; + } + else if (reference_alignment == GIMP_DISTRIBUTE_EVEN_VERTICAL_GAP) + { + gint obj_len; + + ytranslate = ROUND (z0 + fill_offset - z1); + + obj_len = GPOINTER_TO_INT (g_object_get_data (target, "align-height")); + z0 = z0 + fill_offset + obj_len; + } else /* the normal computing, when we don't depend on the * width or height of the reference object */ diff --git a/app/tools/gimpalignoptions.c b/app/tools/gimpalignoptions.c index 9200c54bad..b50b780473 100644 --- a/app/tools/gimpalignoptions.c +++ b/app/tools/gimpalignoptions.c @@ -46,8 +46,8 @@ #define ALIGN_VER_N_BUTTONS 3 #define ALIGN_HOR_N_BUTTONS 3 -#define DISTR_VER_N_BUTTONS 1 -#define DISTR_HOR_N_BUTTONS 1 +#define DISTR_VER_N_BUTTONS 2 +#define DISTR_HOR_N_BUTTONS 2 enum @@ -361,6 +361,12 @@ gimp_align_options_button_new (GimpAlignOptions *options, case GIMP_ARRANGE_VFILL: icon_name = GIMP_ICON_FILL_VERTICAL; break; + case GIMP_DISTRIBUTE_EVEN_HORIZONTAL_GAP: + icon_name = GIMP_ICON_EVEN_HORIZONTAL_GAP; + break; + case GIMP_DISTRIBUTE_EVEN_VERTICAL_GAP: + icon_name = GIMP_ICON_EVEN_VERTICAL_GAP; + break; default: g_return_val_if_reached (NULL); break; @@ -547,12 +553,22 @@ gimp_align_options_gui (GimpToolOptions *tool_options) n = 0; options->priv->distr_ver_button[n++] = gimp_align_options_button_new (options, GIMP_ARRANGE_HFILL, hbox, - _("Distribute targets evenly in the horizontal")); + _("Distribute anchor points of targets evenly in the horizontal")); + options->priv->distr_ver_button[n++] = + gimp_align_options_button_new (options, GIMP_DISTRIBUTE_EVEN_HORIZONTAL_GAP, hbox, + _("Distribute horizontally with even horizontal gaps")); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_box_pack_start (GTK_BOX (section_vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); n = 0; options->priv->distr_hor_button[n++] = gimp_align_options_button_new (options, GIMP_ARRANGE_VFILL, hbox, - _("Distribute targets evenly in the vertical")); + _("Distribute anchor points of targets evenly in the vertical")); + options->priv->distr_hor_button[n++] = + gimp_align_options_button_new (options, GIMP_DISTRIBUTE_EVEN_VERTICAL_GAP, hbox, + _("Distribute vertically with even vertical gaps")); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start (GTK_BOX (section_vbox), hbox, FALSE, FALSE, 0); diff --git a/app/tools/gimpaligntool.c b/app/tools/gimpaligntool.c index 48eff3ec8f..1324e538f6 100644 --- a/app/tools/gimpaligntool.c +++ b/app/tools/gimpaligntool.c @@ -783,6 +783,8 @@ gimp_align_tool_align (GimpAlignTool *align_tool, case GIMP_ALIGN_TOP: case GIMP_ALIGN_VCENTER: case GIMP_ALIGN_BOTTOM: + case GIMP_DISTRIBUTE_EVEN_HORIZONTAL_GAP: + case GIMP_DISTRIBUTE_EVEN_VERTICAL_GAP: offset = 0; break; diff --git a/icons/Color/icon-list.mk b/icons/Color/icon-list.mk index 805dd485cf..92c9fdf161 100644 --- a/icons/Color/icon-list.mk +++ b/icons/Color/icon-list.mk @@ -115,6 +115,8 @@ scalable_images = \ scalable/gimp-device-status.svg \ scalable/gimp-duplicate.svg \ scalable/gimp-dynamics.svg \ + scalable/gimp-even-horizontal-gap.svg \ + scalable/gimp-even-vertical-gap.svg \ scalable/gimp-file-manager.svg \ scalable/gimp-floating-selection.svg \ scalable/gimp-gegl.svg \ @@ -764,6 +766,8 @@ icons24_images = \ 24/gimp-device-status.png \ \ 24/gimp-display-filter.png \ + 24/gimp-even-horizontal-gap.png \ + 24/gimp-even-vertical-gap.png \ 24/gimp-floating-selection.png \ 24/gimp-gegl.png \ 24/gimp-gravity-east.png \ diff --git a/icons/Color/scalable/gimp-even-horizontal-gap.svg b/icons/Color/scalable/gimp-even-horizontal-gap.svg new file mode 100644 index 0000000000..711e2164d0 --- /dev/null +++ b/icons/Color/scalable/gimp-even-horizontal-gap.svg @@ -0,0 +1,134 @@ + + + + + + + + + + + + image/svg+xml + + + + Klaus Staedtler + + + + + + + + + + + + + + + + diff --git a/icons/Color/scalable/gimp-even-vertical-gap.svg b/icons/Color/scalable/gimp-even-vertical-gap.svg new file mode 100644 index 0000000000..c122a1b60d --- /dev/null +++ b/icons/Color/scalable/gimp-even-vertical-gap.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + image/svg+xml + + + + Klaus Staedtler + + + + + + + + + + + + + + + + diff --git a/icons/Symbolic/icon-list.mk b/icons/Symbolic/icon-list.mk index 0edfaa3abd..1bc99b5e8a 100644 --- a/icons/Symbolic/icon-list.mk +++ b/icons/Symbolic/icon-list.mk @@ -115,6 +115,8 @@ scalable_images = \ scalable/gimp-device-status-symbolic.svg \ scalable/gimp-duplicate-symbolic.svg \ scalable/gimp-dynamics-symbolic.svg \ + scalable/gimp-even-horizontal-gap-symbolic.svg \ + scalable/gimp-even-vertical-gap-symbolic.svg \ scalable/gimp-file-manager-symbolic.svg \ scalable/gimp-floating-selection-symbolic.svg \ scalable/gimp-gegl-symbolic.svg \ @@ -764,6 +766,8 @@ icons24_images = \ 24/gimp-device-status-symbolic.symbolic.png \ \ 24/gimp-display-filter-symbolic.symbolic.png \ + 24/gimp-even-horizontal-gap-symbolic.symbolic.png \ + 24/gimp-even-vertical-gap-symbolic.symbolic.png \ 24/gimp-floating-selection-symbolic.symbolic.png \ 24/gimp-gegl-symbolic.symbolic.png \ 24/gimp-gravity-east-symbolic.symbolic.png \ diff --git a/icons/Symbolic/scalable/gimp-even-horizontal-gap-symbolic.svg b/icons/Symbolic/scalable/gimp-even-horizontal-gap-symbolic.svg new file mode 100644 index 0000000000..cd2093df4b --- /dev/null +++ b/icons/Symbolic/scalable/gimp-even-horizontal-gap-symbolic.svg @@ -0,0 +1,195 @@ + + + + + + + image/svg+xml + + + + Barbara Muraus, Jakub Steiner, Klaus Staedtler + + + Images originally created as the "Art Libre" icon set. Extended and adopted for GIMP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/Symbolic/scalable/gimp-even-vertical-gap-symbolic.svg b/icons/Symbolic/scalable/gimp-even-vertical-gap-symbolic.svg new file mode 100644 index 0000000000..6b803c0dc6 --- /dev/null +++ b/icons/Symbolic/scalable/gimp-even-vertical-gap-symbolic.svg @@ -0,0 +1,196 @@ + + + + + + + image/svg+xml + + + + Barbara Muraus, Jakub Steiner, Klaus Staedtler + + + Images originally created as the "Art Libre" icon set. Extended and adopted for GIMP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/icon-lists/bitmap_24.list b/icons/icon-lists/bitmap_24.list index bc071dc0e5..25e7f40e3c 100644 --- a/icons/icon-lists/bitmap_24.list +++ b/icons/icon-lists/bitmap_24.list @@ -29,6 +29,8 @@ gimp-device-status # Used as GimpViewableDialog icon in gimpdisplayshell-filter-dialog.c, # i.e. as GTK_ICON_SIZE_LARGE_TOOLBAR (24px). gimp-display-filter +gimp-even-horizontal-gap +gimp-even-vertical-gap gimp-floating-selection gimp-gegl gimp-gravity-east diff --git a/icons/icon-lists/scalable.list b/icons/icon-lists/scalable.list index 5e9a86df1a..5fbeb97ddb 100644 --- a/icons/icon-lists/scalable.list +++ b/icons/icon-lists/scalable.list @@ -106,6 +106,8 @@ gimp-detach gimp-device-status gimp-duplicate gimp-dynamics +gimp-even-horizontal-gap +gimp-even-vertical-gap gimp-file-manager gimp-floating-selection gimp-gegl diff --git a/libgimpwidgets/gimpicons.h b/libgimpwidgets/gimpicons.h index e59501cee6..1c0309588f 100644 --- a/libgimpwidgets/gimpicons.h +++ b/libgimpwidgets/gimpicons.h @@ -210,6 +210,9 @@ G_BEGIN_DECLS #define GIMP_ICON_EDIT_REDO "edit-redo" #define GIMP_ICON_EDIT_UNDO "edit-undo" +#define GIMP_ICON_EVEN_HORIZONTAL_GAP "gimp-even-horizontal-gap" +#define GIMP_ICON_EVEN_VERTICAL_GAP "gimp-even-vertical-gap" + #define GIMP_ICON_FILL_HORIZONTAL "gimp-hfill" #define GIMP_ICON_FILL_VERTICAL "gimp-vfill"