mirror of https://github.com/GNOME/gimp.git
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:
parent
8d85c0c41c
commit
72ac53705f
|
@ -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);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
}
|
||||
|
|
|
@ -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 \
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 7.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.9 KiB |
Loading…
Reference in New Issue