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.
This commit is contained in:
João S. O. Bueno 2014-03-13 03:38:53 -03:00
parent 8d85c0c41c
commit 72ac53705f
11 changed files with 111 additions and 15 deletions

View File

@ -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 }
};

View File

@ -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;

View File

@ -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);
}
z0 = GPOINTER_TO_INT (g_object_get_data (reference, "align-offset"));
if (object_list)
{
GList *l;
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 (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;
}
/* 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));
}

View File

@ -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);

View File

@ -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 ())

View File

@ -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;
}

View File

@ -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 },

View File

@ -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"

View File

@ -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 \

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB