1
/* GIMP - The GNU Image Manipulation Program
2
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
#include <glib-object.h>
23
#include "core-types.h"
25
#include "gimpimage.h"
26
#include "gimpimage-arrange.h"
27
#include "gimpimage-guides.h"
28
#include "gimpimage-undo.h"
30
#include "gimpchannel.h"
31
#include "gimpdrawable.h"
32
#include "gimpguide.h"
34
#include "gimp-intl.h"
36
static GList * sort_by_offset (GList *list);
37
static void compute_offsets (GList *list,
38
GimpAlignmentType alignment);
39
static void compute_offset (GObject *object,
40
GimpAlignmentType alignment);
41
static gint offset_compare (gconstpointer a,
46
* gimp_image_arrange_objects:
47
* @image: The #GimpImage to which the objects belong.
48
* @list: A #GList of objects to be aligned.
49
* @alignment: The point on each target object to bring into alignment.
50
* @reference: The #GObject to align the targets with, or #NULL.
51
* @reference_alignment: The point on the reference object to align the target item with..
52
* @offset: How much to shift the target from perfect alignment..
54
* This function shifts the positions of a set of target objects, which can be
55
* "items" or guides, to bring them into a specified type of alignment with a
56
* reference object, which can be an item, guide, or image. If the requested
57
* alignment does not make sense (i.e., trying to align a vertical guide vertically),
58
* nothing happens and no error message is generated.
60
* The objects in the list are sorted into increasing order before
61
* being arranged, where the order is defined by the type of alignment
62
* being requested. If the @reference argument is #NULL, then the first
63
* object in the sorted list is used as reference.
65
* When there are multiple target objects, they are arranged so that the spacing
66
* between consecutive ones is given by the argument @offset.
69
gimp_image_arrange_objects (GimpImage *image,
71
GimpAlignmentType alignment,
73
GimpAlignmentType reference_alignment,
76
gboolean do_x = FALSE;
77
gboolean do_y = FALSE;
81
g_return_if_fail (GIMP_IS_IMAGE (image));
82
g_return_if_fail (G_IS_OBJECT (reference) || reference == NULL);
84
/* get offsets used for sorting */
87
/* order vertically for horizontal alignment */
89
case GIMP_ALIGN_HCENTER:
90
case GIMP_ALIGN_RIGHT:
92
compute_offsets (list, GIMP_ALIGN_TOP);
94
/* order horizontally for horizontal arrangement */
95
case GIMP_ARRANGE_LEFT:
96
case GIMP_ARRANGE_HCENTER:
97
case GIMP_ARRANGE_RIGHT:
99
compute_offsets (list, alignment);
101
/* order horizontally for vertical alignment */
103
case GIMP_ALIGN_VCENTER:
104
case GIMP_ALIGN_BOTTOM:
106
compute_offsets (list, GIMP_ALIGN_LEFT);
108
/* order vertically for vertical arrangement */
109
case GIMP_ARRANGE_TOP:
110
case GIMP_ARRANGE_VCENTER:
111
case GIMP_ARRANGE_BOTTOM:
113
compute_offsets (list, alignment);
117
object_list = sort_by_offset (list);
119
/* now get offsets used for aligning */
120
compute_offsets (list, alignment);
122
if (reference == NULL)
124
reference = G_OBJECT (object_list->data);
125
object_list = g_list_next (object_list);
128
compute_offset (reference, reference_alignment);
130
z0 = GPOINTER_TO_INT (g_object_get_data (reference, "align-offset"));
137
/* FIXME: undo group type is wrong */
138
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_ITEM_DISPLACE,
139
_("Arrange Objects"));
141
for (l = object_list, n = 1; l; l = g_list_next (l), n++)
143
GObject *target = G_OBJECT (l->data);
148
z1 = GPOINTER_TO_INT (g_object_get_data (target,
152
xtranslate = z0 - z1 + n * offset;
155
ytranslate = z0 - z1 + n * offset;
157
/* now actually align the target object */
158
if (GIMP_IS_ITEM (target))
160
gimp_item_translate (GIMP_ITEM (target),
161
xtranslate, ytranslate, TRUE);
163
else if (GIMP_IS_GUIDE (target))
165
GimpGuide *guide = GIMP_GUIDE (target);
167
switch (gimp_guide_get_orientation (guide))
169
case GIMP_ORIENTATION_VERTICAL:
170
gimp_image_move_guide (image, guide, z1 + xtranslate, TRUE);
171
gimp_image_update_guide (image, guide);
174
case GIMP_ORIENTATION_HORIZONTAL:
175
gimp_image_move_guide (image, guide, z1 + ytranslate, TRUE);
176
gimp_image_update_guide (image, guide);
185
gimp_image_undo_group_end (image);
188
g_list_free (object_list);
193
sort_by_offset (GList *list)
195
return g_list_sort (g_list_copy (list),
201
offset_compare (gconstpointer a,
204
gint offset1 = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (a),
206
gint offset2 = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (b),
209
return offset1 - offset2;
213
* this function computes the position of the alignment point
214
* for each object in the list, and attaches it to the
215
* object as object data.
218
compute_offsets (GList *list,
219
GimpAlignmentType alignment)
223
for (l = list; l; l = g_list_next (l))
224
compute_offset (G_OBJECT (l->data), alignment);
228
compute_offset (GObject *object,
229
GimpAlignmentType alignment)
231
gint object_offset_x = 0;
232
gint object_offset_y = 0;
233
gint object_height = 0;
234
gint object_width = 0;
237
if (GIMP_IS_IMAGE (object))
239
GimpImage *image = GIMP_IMAGE (object);
243
object_height = gimp_image_get_height (image);
244
object_width = gimp_image_get_width (image);
246
else if (GIMP_IS_CHANNEL (object))
248
/* for channels, we use the bounds of the visible area, not
249
the layer bounds. This includes the selection channel */
251
GimpChannel *channel = GIMP_CHANNEL (object);
253
if (gimp_channel_is_empty (channel))
255
/* fall back on using the offsets instead */
256
GimpItem *item = GIMP_ITEM (object);
258
gimp_item_offsets (item, &object_offset_x, &object_offset_y);
259
object_height = gimp_item_height (item);
260
object_width = gimp_item_width (item);
266
gimp_channel_bounds (channel, &x1, &y1, &x2, &y2);
267
object_offset_x = x1;
268
object_offset_y = y1;
269
object_height = y2 - y1;
270
object_width = x2 - x1;
273
else if (GIMP_IS_ITEM (object))
275
GimpItem *item = GIMP_ITEM (object);
277
gimp_item_offsets (item, &object_offset_x, &object_offset_y);
278
object_height = gimp_item_height (item);
279
object_width = gimp_item_width (item);
281
else if (GIMP_IS_GUIDE (object))
283
GimpGuide *guide = GIMP_GUIDE (object);
285
switch (gimp_guide_get_orientation (guide))
287
case GIMP_ORIENTATION_VERTICAL:
288
object_offset_x = gimp_guide_get_position (guide);
292
case GIMP_ORIENTATION_HORIZONTAL:
293
object_offset_y = gimp_guide_get_position (guide);
303
g_printerr ("Alignment object is not an image, item or guide.\n");
308
case GIMP_ALIGN_LEFT:
309
case GIMP_ARRANGE_LEFT:
310
offset = object_offset_x;
312
case GIMP_ALIGN_HCENTER:
313
case GIMP_ARRANGE_HCENTER:
314
offset = object_offset_x + object_width/2;
316
case GIMP_ALIGN_RIGHT:
317
case GIMP_ARRANGE_RIGHT:
318
offset = object_offset_x + object_width;
321
case GIMP_ARRANGE_TOP:
322
offset = object_offset_y;
324
case GIMP_ALIGN_VCENTER:
325
case GIMP_ARRANGE_VCENTER:
326
offset = object_offset_y + object_height/2;
328
case GIMP_ALIGN_BOTTOM:
329
case GIMP_ARRANGE_BOTTOM:
330
offset = object_offset_y + object_height;
333
g_assert_not_reached ();
336
g_object_set_data (object, "align-offset",
337
GINT_TO_POINTER (offset));