Adds "fill" arrange modes to the Align Tool

The Align Tool had to be used in a very hacky way if one
intended to evenly distribute items across an image,
or other reference object (it would actually require one to
calculate the item spacing out of GIMP). This adds vertical
and horizontal fill modes: the reference object is divided
in N equal segments, where N is the number of items,
and each item is placed in the center of one of
these segments. The existing "offset" parameter
is used as an extra margin for the distribution,
and can be set to negative values, so that the items can
even get moved outside the boundaries of the reference object.
parent 8d85c0c4
......@@ -450,6 +450,8 @@ gimp_alignment_type_get_type (void)
{ GIMP_ARRANGE_TOP, "GIMP_ARRANGE_TOP", "arrange-top" },
{ GIMP_ARRANGE_VCENTER, "GIMP_ARRANGE_VCENTER", "arrange-vcenter" },
{ GIMP_ARRANGE_BOTTOM, "GIMP_ARRANGE_BOTTOM", "arrange-bottom" },
{ GIMP_ARRANGE_HFILL, "GIMP_ARRANGE_HFILL", "arrange-hfill" },
{ GIMP_ARRANGE_VFILL, "GIMP_ARRANGE_VFILL", "arrange-vfill" },
{ 0, NULL, NULL }
};
......@@ -467,6 +469,8 @@ gimp_alignment_type_get_type (void)
{ GIMP_ARRANGE_TOP, "GIMP_ARRANGE_TOP", NULL },
{ GIMP_ARRANGE_VCENTER, "GIMP_ARRANGE_VCENTER", NULL },
{ GIMP_ARRANGE_BOTTOM, "GIMP_ARRANGE_BOTTOM", NULL },
{ GIMP_ARRANGE_HFILL, "GIMP_ARRANGE_HFILL", NULL },
{ GIMP_ARRANGE_VFILL, "GIMP_ARRANGE_VFILL", NULL },
{ 0, NULL, NULL }
};
......
......@@ -233,7 +233,9 @@ typedef enum /*< pdb-skip >*/
GIMP_ARRANGE_RIGHT,
GIMP_ARRANGE_TOP,
GIMP_ARRANGE_VCENTER,
GIMP_ARRANGE_BOTTOM
GIMP_ARRANGE_BOTTOM,
GIMP_ARRANGE_HFILL,
GIMP_ARRANGE_VFILL
} GimpAlignmentType;
......
......@@ -67,7 +67,9 @@ static gint offset_compare (gconstpointer a,
* object in the sorted list is used as reference.
*
* When there are multiple target objects, they are arranged so that the spacing
* between consecutive ones is given by the argument @offset.
* between consecutive ones is given by the argument @offset but for HFILL and VFILL -
* in this case, @offset works as an internal margin for the distribution
* (and it can be negative).
*/
void
gimp_image_arrange_objects (GimpImage *image,
......@@ -99,6 +101,7 @@ gimp_image_arrange_objects (GimpImage *image,
case GIMP_ARRANGE_LEFT:
case GIMP_ARRANGE_HCENTER:
case GIMP_ARRANGE_RIGHT:
case GIMP_ARRANGE_HFILL:
do_x = TRUE;
compute_offsets (list, alignment);
break;
......@@ -113,6 +116,7 @@ gimp_image_arrange_objects (GimpImage *image,
case GIMP_ARRANGE_TOP:
case GIMP_ARRANGE_VCENTER:
case GIMP_ARRANGE_BOTTOM:
case GIMP_ARRANGE_VFILL:
do_y = TRUE;
compute_offsets (list, alignment);
break;
......@@ -127,36 +131,79 @@ gimp_image_arrange_objects (GimpImage *image,
{
reference = G_OBJECT (object_list->data);
object_list = g_list_next (object_list);
reference_alignment = alignment;
}
else
compute_offset (reference, reference_alignment);
{
compute_offset (reference, reference_alignment);
}
z0 = GPOINTER_TO_INT (g_object_get_data (reference, "align-offset"));
if (object_list)
{
GList *l;
gint n;
GList *lst;
gint n;
gint distr_width = 0;
gint distr_height = 0;
gdouble fill_offset = 0;
if (reference_alignment == GIMP_ARRANGE_HFILL)
{
distr_width = GPOINTER_TO_INT (g_object_get_data
(reference, "align-width"));
/* The offset parameter works as an internal margin */
fill_offset = (distr_width - 2 * offset) /
g_list_length (object_list);
}
if (reference_alignment == GIMP_ARRANGE_VFILL)
{
distr_height = GPOINTER_TO_INT (g_object_get_data
(reference, "align-height"));
fill_offset = (distr_height - 2 * offset) /
g_list_length (object_list);
}
/* FIXME: undo group type is wrong */
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_ITEM_DISPLACE,
C_("undo-type", "Arrange Objects"));
for (l = object_list, n = 1; l; l = g_list_next (l), n++)
for (lst = object_list, n = 1; lst; lst = g_list_next (lst), n++)
{
GObject *target = G_OBJECT (l->data);
GObject *target = G_OBJECT (lst->data);
gint xtranslate = 0;
gint ytranslate = 0;
gint width;
gint height;
gint z1;
z1 = GPOINTER_TO_INT (g_object_get_data (target,
"align-offset"));
if (do_x)
xtranslate = z0 - z1 + n * offset;
if (reference_alignment == GIMP_ARRANGE_HFILL)
{
width = GPOINTER_TO_INT (g_object_get_data (target,
"align-width"));
xtranslate = ROUND (z0 - z1 + (n - 0.5) * fill_offset -
width/2.0 + offset);
}
else if (reference_alignment == GIMP_ARRANGE_VFILL)
{
height = GPOINTER_TO_INT (g_object_get_data (target,
"align-height"));
ytranslate = ROUND (z0 - z1 + (n - 0.5) * fill_offset -
height/2.0 + offset);
}
else /* the normal computing, when we don't depend on the
* width or height of the reference object
*/
{
if (do_x)
xtranslate = z0 - z1 + n * offset;
if (do_y)
ytranslate = z0 - z1 + n * offset;
if (do_y)
ytranslate = z0 - z1 + n * offset;
}
/* now actually align the target object */
if (GIMP_IS_ITEM (target))
......@@ -220,10 +267,10 @@ static void
compute_offsets (GList *list,
GimpAlignmentType alignment)
{
GList *l;
GList *lst;
for (l = list; l; l = g_list_next (l))
compute_offset (G_OBJECT (l->data), alignment);
for (lst = list; lst; lst = g_list_next (lst))
compute_offset (G_OBJECT (lst->data), alignment);
}
static void
......@@ -325,6 +372,7 @@ compute_offset (GObject *object,
{
case GIMP_ALIGN_LEFT:
case GIMP_ARRANGE_LEFT:
case GIMP_ARRANGE_HFILL:
offset = object_offset_x;
break;
case GIMP_ALIGN_HCENTER:
......@@ -337,6 +385,7 @@ compute_offset (GObject *object,
break;
case GIMP_ALIGN_TOP:
case GIMP_ARRANGE_TOP:
case GIMP_ARRANGE_VFILL:
offset = object_offset_y;
break;
case GIMP_ALIGN_VCENTER:
......@@ -353,4 +402,18 @@ compute_offset (GObject *object,
g_object_set_data (object, "align-offset",
GINT_TO_POINTER (offset));
/* These are only used for HFILL and VFILL, but
* since the call to gimp_image_arrange_objects
* allows for two different alignments (object and reference_alignment)
* we better be on the safe side in case they differ.
* (the current implementation of the align tool always
* pass the same value to both parameters)
*/
g_object_set_data (object, "align-width",
GINT_TO_POINTER (object_width));
g_object_set_data (object, "align-height",
GINT_TO_POINTER (object_height));
}
......@@ -229,6 +229,12 @@ gimp_align_options_button_new (GimpAlignOptions *options,
case GIMP_ARRANGE_BOTTOM:
stock_id = GIMP_STOCK_GRAVITY_SOUTH;
break;
case GIMP_ARRANGE_HFILL:
stock_id = GIMP_STOCK_HFILL;
break;
case GIMP_ARRANGE_VFILL:
stock_id = GIMP_STOCK_VFILL;
break;
default:
g_return_val_if_reached (NULL);
break;
......@@ -340,6 +346,10 @@ gimp_align_options_gui (GimpToolOptions *tool_options)
gimp_align_options_button_new (options, GIMP_ARRANGE_RIGHT, hbox,
_("Distribute right edges of targets"));
options->button[n++] =
gimp_align_options_button_new (options, GIMP_ARRANGE_HFILL, hbox,
_("Distribute targets evenly in the horizontal"));
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_box_pack_start (GTK_BOX (align_vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
......@@ -356,6 +366,10 @@ gimp_align_options_gui (GimpToolOptions *tool_options)
gimp_align_options_button_new (options, GIMP_ARRANGE_BOTTOM, hbox,
_("Distribute bottoms of targets"));
options->button[n++] =
gimp_align_options_button_new (options, GIMP_ARRANGE_VFILL, hbox,
_("Distribute targets evenly in the vertical"));
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_box_pack_start (GTK_BOX (align_vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
......
......@@ -22,7 +22,7 @@
#include "core/gimptooloptions.h"
#define ALIGN_OPTIONS_N_BUTTONS 12
#define ALIGN_OPTIONS_N_BUTTONS 14
#define GIMP_TYPE_ALIGN_OPTIONS (gimp_align_options_get_type ())
......
......@@ -740,6 +740,8 @@ gimp_align_tool_align (GimpAlignTool *align_tool,
case GIMP_ARRANGE_TOP:
case GIMP_ARRANGE_VCENTER:
case GIMP_ARRANGE_BOTTOM:
case GIMP_ARRANGE_HFILL:
case GIMP_ARRANGE_VFILL:
offset = options->offset_x;
break;
}
......
......@@ -158,6 +158,9 @@ static const GtkStockItem gimp_stock_items[] =
{ GIMP_STOCK_HCENTER, NULL, 0, 0, LIBGIMP_DOMAIN },
{ GIMP_STOCK_VCENTER, NULL, 0, 0, LIBGIMP_DOMAIN },
{ GIMP_STOCK_HFILL, NULL, 0, 0, LIBGIMP_DOMAIN },
{ GIMP_STOCK_VFILL, NULL, 0, 0, LIBGIMP_DOMAIN },
{ GIMP_STOCK_HCHAIN, NULL, 0, 0, LIBGIMP_DOMAIN },
{ GIMP_STOCK_HCHAIN_BROKEN, NULL, 0, 0, LIBGIMP_DOMAIN },
{ GIMP_STOCK_VCHAIN, NULL, 0, 0, LIBGIMP_DOMAIN },
......@@ -375,6 +378,9 @@ gimp_stock_button_pixbufs[] =
{ GIMP_STOCK_HCENTER, stock_hcenter_24 },
{ GIMP_STOCK_VCENTER, stock_vcenter_24 },
{ GIMP_STOCK_HFILL, stock_hfill_24 },
{ GIMP_STOCK_VFILL, stock_vfill_24 },
{ GIMP_STOCK_HCHAIN, stock_hchain_24 },
{ GIMP_STOCK_HCHAIN_BROKEN, stock_hchain_broken_24 },
{ GIMP_STOCK_VCHAIN, stock_vchain_24 },
......
......@@ -67,6 +67,9 @@ G_BEGIN_DECLS
#define GIMP_STOCK_HCENTER "gimp-hcenter"
#define GIMP_STOCK_VCENTER "gimp-vcenter"
#define GIMP_STOCK_HFILL "gimp-hfill"
#define GIMP_STOCK_VFILL "gimp-vfill"
#define GIMP_STOCK_HCHAIN "gimp-hchain"
#define GIMP_STOCK_HCHAIN_BROKEN "gimp-hchain-broken"
#define GIMP_STOCK_VCHAIN "gimp-vchain"
......
......@@ -178,6 +178,7 @@ STOCK_BUTTON_IMAGES = \
stock-hcenter-24.png \
stock-hchain-24.png \
stock-hchain-broken-24.png \
stock-hfill-24.png \
stock-histogram-22.png \
stock-image-24.png \
stock-images-24.png \
......@@ -219,6 +220,7 @@ STOCK_BUTTON_IMAGES = \
stock-vcenter-24.png \
stock-vchain-24.png \
stock-vchain-broken-24.png \
stock-vfill-24.png \
stock-video-24.png \
stock-warning-24.png \
stock-web-24.png \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment