Index: gimp/app/core/core-enums.c
===================================================================
RCS file: /cvs/gnome/gimp/app/core/core-enums.c,v
retrieving revision 1.75
diff -u -p -r1.75 core-enums.c
--- gimp/app/core/core-enums.c	22 Jan 2005 23:38:35 -0000	1.75
+++ gimp/app/core/core-enums.c	23 Feb 2005 17:50:38 -0000
@@ -145,6 +145,42 @@ gimp_gravity_type_get_type (void)
 }
 
 GType
+gimp_alignment_type_get_type (void)
+{
+  static const GEnumValue values[] =
+  {
+    { GIMP_ALIGN_LEFT, "GIMP_ALIGN_LEFT", "left" },
+    { GIMP_ALIGN_CENTER, "GIMP_ALIGN_CENTER", "center" },
+    { GIMP_ALIGN_RIGHT, "GIMP_ALIGN_RIGHT", "right" },
+    { GIMP_ALIGN_TOP, "GIMP_ALIGN_TOP", "top" },
+    { GIMP_ALIGN_MIDDLE, "GIMP_ALIGN_MIDDLE", "middle" },
+    { GIMP_ALIGN_BOTTOM, "GIMP_ALIGN_BOTTOM", "bottom" },
+    { 0, NULL, NULL }
+  };
+
+  static const GimpEnumDesc descs[] =
+  {
+    { GIMP_ALIGN_LEFT, "GIMP_ALIGN_LEFT", NULL },
+    { GIMP_ALIGN_CENTER, "GIMP_ALIGN_CENTER", NULL },
+    { GIMP_ALIGN_RIGHT, "GIMP_ALIGN_RIGHT", NULL },
+    { GIMP_ALIGN_TOP, "GIMP_ALIGN_TOP", NULL },
+    { GIMP_ALIGN_MIDDLE, "GIMP_ALIGN_MIDDLE", NULL },
+    { GIMP_ALIGN_BOTTOM, "GIMP_ALIGN_BOTTOM", NULL },
+    { 0, NULL, NULL }
+  };
+
+  static GType type = 0;
+
+  if (! type)
+    {
+      type = g_enum_register_static ("GimpAlignmentType", values);
+      gimp_enum_set_value_descriptions (type, descs);
+    }
+
+  return type;
+}
+
+GType
 gimp_fill_type_get_type (void)
 {
   static const GEnumValue values[] =
Index: gimp/app/core/core-enums.h
===================================================================
RCS file: /cvs/gnome/gimp/app/core/core-enums.h,v
retrieving revision 1.91
diff -u -p -r1.91 core-enums.h
--- gimp/app/core/core-enums.h	22 Jan 2005 23:38:35 -0000	1.91
+++ gimp/app/core/core-enums.h	23 Feb 2005 17:50:38 -0000
@@ -95,6 +95,21 @@ typedef enum  /*< pdb-skip >*/
 } GimpGravityType;
 
 
+#define GIMP_TYPE_ALIGNMENT (gimp_alignment_type_get_type ())
+
+GType gimp_alignment_type_get_type (void) G_GNUC_CONST;
+
+typedef enum  /*< pdb-skip >*/
+{
+  GIMP_ALIGN_LEFT,
+  GIMP_ALIGN_CENTER,
+  GIMP_ALIGN_RIGHT,
+  GIMP_ALIGN_TOP,
+  GIMP_ALIGN_MIDDLE,
+  GIMP_ALIGN_BOTTOM
+} GimpAlignmentType;
+
+
 #define GIMP_TYPE_FILL_TYPE (gimp_fill_type_get_type ())
 
 GType gimp_fill_type_get_type (void) G_GNUC_CONST;
Index: gimp/app/core/gimpitem.c
===================================================================
RCS file: /cvs/gnome/gimp/app/core/gimpitem.c,v
retrieving revision 1.70
diff -u -p -r1.70 gimpitem.c
--- gimp/app/core/gimpitem.c	15 Jan 2005 19:17:11 -0000	1.70
+++ gimp/app/core/gimpitem.c	23 Feb 2005 17:50:39 -0000
@@ -1249,3 +1249,132 @@ gimp_item_get_linked (const GimpItem *it
 
   return item->linked;
 }
+
+/**
+ * gimp_item_align:
+ * @target:               The #GimpItem to move.
+ * @target_alignment:     The part of the target to align..
+ * @reference:            The #GimpItem to align the target with.
+ * @reference_alignment:  The part of the reference item to align the target item with..
+ * @offset:               How much to shift the target from perfect alignment..
+ * @push_undo:            If #TRUE, create an entry in the image's undo stack
+ *                        for this action.
+ *
+ * Aligns the target item with the reference item in the specified way.  If
+ * the reference item is #NULL, then the target item is aligned with the
+ * image it belongs to.
+ */
+void
+gimp_item_align (GimpItem          *target,
+                 GimpAlignmentType  target_alignment,
+                 GimpItem          *reference,
+                 GimpAlignmentType  reference_alignment,
+                 gint               offset,
+                 gboolean           push_undo)
+{
+  gboolean do_x       = FALSE;
+  gboolean do_y       = FALSE;
+  gint     xtranslate = 0;
+  gint     ytranslate = 0;
+  gint     reference_offset_x;
+  gint     reference_offset_y;
+  gint     reference_height;
+  gint     reference_width;
+  gint     x0         = 0;
+  gint     y0         = 0;
+  gint     x1         = 0;
+  gint     y1         = 0;
+
+  if (!target)
+    return;
+
+  if (! (reference || target->gimage))
+    return;
+
+  if (reference)
+    {
+      reference_offset_x = reference->offset_x;
+      reference_offset_y = reference->offset_y;
+      reference_height   = reference->height;
+      reference_width    = reference->width;
+    }
+  else
+    {
+      reference_offset_x = 0;
+      reference_offset_y = 0;
+      reference_height   = gimp_image_get_height (target->gimage);
+      reference_width    = gimp_image_get_width (target->gimage);
+    }
+
+  switch (reference_alignment)
+    {
+    case GIMP_ALIGN_LEFT:
+      do_x = TRUE;
+      x0 = reference_offset_x;
+      break;
+    case GIMP_ALIGN_CENTER:
+      do_x = TRUE;
+      x0 = reference_offset_x + reference_width/2;
+      break;
+    case GIMP_ALIGN_RIGHT:
+      do_x = TRUE;
+      x0 = reference_offset_x + reference_width;
+      break;
+    case GIMP_ALIGN_TOP:
+      do_y = TRUE;
+      y0 = reference_offset_y;
+      break;
+    case GIMP_ALIGN_MIDDLE:
+      do_y = TRUE;
+      y0 = reference_offset_y + reference_height/2;
+      break;
+    case GIMP_ALIGN_BOTTOM:
+      do_y = TRUE;
+      y0 = reference_offset_y + reference_height;
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+
+  if (do_x)
+    {
+      switch (target_alignment)
+        {
+        case GIMP_ALIGN_LEFT:
+          x1 = target->offset_x;
+          break;
+        case GIMP_ALIGN_CENTER:
+          x1 = target->offset_x + target->width/2;
+          break;
+        case GIMP_ALIGN_RIGHT:
+          x1 = target->offset_x + target->width;
+          break;
+        default:
+          g_assert_not_reached ();
+        }
+
+      xtranslate = x0 - x1 + offset;
+    }
+
+  if (do_y)
+    {
+      switch (target_alignment)
+        {
+        case GIMP_ALIGN_TOP:
+          y1 = target->offset_y;
+          break;
+        case GIMP_ALIGN_MIDDLE:
+          y1 = target->offset_y + target->height/2;
+          break;
+        case GIMP_ALIGN_BOTTOM:
+          y1 = target->offset_y + target->height;
+          break;
+        default:
+          g_assert_not_reached ();
+        }
+
+      ytranslate = y0 - y1 + offset;
+    }
+
+  gimp_item_translate (target, xtranslate, ytranslate, push_undo);
+}
Index: gimp/app/core/gimpitem.h
===================================================================
RCS file: /cvs/gnome/gimp/app/core/gimpitem.h,v
retrieving revision 1.40
diff -u -p -r1.40 gimpitem.h
--- gimp/app/core/gimpitem.h	13 Jan 2005 18:17:23 -0000	1.40
+++ gimp/app/core/gimpitem.h	23 Feb 2005 17:50:39 -0000
@@ -253,5 +253,12 @@ void            gimp_item_set_linked    
                                             gboolean        push_undo);
 gboolean        gimp_item_get_linked       (const GimpItem *item);
 
+void            gimp_item_align            (GimpItem          *target,
+                                            GimpAlignmentType  target_alignment,
+                                            GimpItem          *refeence,
+                                            GimpAlignmentType  reference_alignment,
+                                            gint               offset,
+                                            gboolean           push_undo);
+
 
 #endif /* __GIMP_ITEM_H__ */
Index: gimp/app/tools/Makefile.am
===================================================================
RCS file: /cvs/gnome/gimp/app/tools/Makefile.am,v
retrieving revision 1.88
diff -u -p -r1.88 Makefile.am
--- gimp/app/tools/Makefile.am	13 Feb 2005 15:08:07 -0000	1.88
+++ gimp/app/tools/Makefile.am	23 Feb 2005 17:50:39 -0000
@@ -14,6 +14,10 @@ libapptools_a_sources = \
 	\
 	gimpairbrushtool.c		\
 	gimpairbrushtool.h		\
+	gimpalignoptions.c		\
+	gimpalignoptions.h		\
+	gimpaligntool.c			\
+	gimpaligntool.h			\
 	gimpblendoptions.c		\
 	gimpblendoptions.h		\
 	gimpblendtool.c			\
Index: gimp/app/tools/gimp-tools.c
===================================================================
RCS file: /cvs/gnome/gimp/app/tools/gimp-tools.c,v
retrieving revision 1.16
diff -u -p -r1.16 gimp-tools.c
--- gimp/app/tools/gimp-tools.c	31 Jan 2005 18:43:27 -0000	1.16
+++ gimp/app/tools/gimp-tools.c	23 Feb 2005 17:50:39 -0000
@@ -35,6 +35,7 @@
 #include "tool_manager.h"
 
 #include "gimpairbrushtool.h"
+#include "gimpaligntool.h"
 #include "gimpblendtool.h"
 #include "gimpbrightnesscontrasttool.h"
 #include "gimpbucketfilltool.h"
@@ -136,6 +137,7 @@ gimp_tools_init (Gimp *gimp)
     gimp_rotate_tool_register,
     gimp_crop_tool_register,
     gimp_move_tool_register,
+    gimp_align_tool_register,
 
     /*  non-modifying tools  */
 
Index: gimp/app/tools/gimpalignoptions.c
===================================================================
RCS file: gimp/app/tools/gimpalignoptions.c
diff -N gimp/app/tools/gimpalignoptions.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gimp/app/tools/gimpalignoptions.c	23 Feb 2005 17:50:39 -0000
@@ -0,0 +1,164 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+
+#include "libgimpconfig/gimpconfig.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "tools-types.h"
+
+#include "core/gimptoolinfo.h"
+
+#include "widgets/gimpwidgets-utils.h"
+
+#include "gimpalignoptions.h"
+#include "gimptooloptions-gui.h"
+
+#include "gimp-intl.h"
+
+
+enum
+{
+  PROP_0,
+  PROP_ALIGN_TYPE
+};
+
+
+static void   gimp_align_options_class_init (GimpAlignOptionsClass *options_class);
+
+static void   gimp_align_options_set_property (GObject         *object,
+                                              guint            property_id,
+                                              const GValue    *value,
+                                              GParamSpec      *pspec);
+static void   gimp_align_options_get_property (GObject         *object,
+                                              guint            property_id,
+                                              GValue          *value,
+                                              GParamSpec      *pspec);
+
+
+static GimpToolOptionsClass *parent_class = NULL;
+
+
+GType
+gimp_align_options_get_type (void)
+{
+  static GType type = 0;
+
+  if (! type)
+    {
+      static const GTypeInfo info =
+      {
+        sizeof (GimpAlignOptionsClass),
+        (GBaseInitFunc) NULL,
+        (GBaseFinalizeFunc) NULL,
+        (GClassInitFunc) gimp_align_options_class_init,
+        NULL,           /* class_finalize */
+        NULL,           /* class_data     */
+        sizeof (GimpAlignOptions),
+        0,              /* n_preallocs    */
+        (GInstanceInitFunc) NULL
+      };
+
+      type = g_type_register_static (GIMP_TYPE_TOOL_OPTIONS,
+                                     "GimpAlignOptions",
+                                     &info, 0);
+    }
+
+  return type;
+}
+
+static void
+gimp_align_options_class_init (GimpAlignOptionsClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  object_class->set_property = gimp_align_options_set_property;
+  object_class->get_property = gimp_align_options_get_property;
+
+  GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_ALIGN_TYPE,
+                                 "align-type", NULL,
+                                 GIMP_TYPE_TRANSFORM_TYPE,
+                                 GIMP_TRANSFORM_TYPE_LAYER,
+                                 0);
+}
+
+static void
+gimp_align_options_set_property (GObject      *object,
+                                guint         property_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+  GimpAlignOptions *options = GIMP_ALIGN_OPTIONS (object);
+
+  switch (property_id)
+    {
+    case PROP_ALIGN_TYPE:
+      options->align_type = g_value_get_enum (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_align_options_get_property (GObject    *object,
+                                guint       property_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+  GimpAlignOptions *options = GIMP_ALIGN_OPTIONS (object);
+
+  switch (property_id)
+    {
+    case PROP_ALIGN_TYPE:
+      g_value_set_enum (value, options->align_type);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+GtkWidget *
+gimp_align_options_gui (GimpToolOptions *tool_options)
+{
+  GObject   *config = G_OBJECT (tool_options);
+  GtkWidget *vbox;
+  GtkWidget *hbox;
+  GtkWidget *label;
+
+  vbox = gimp_tool_options_gui (tool_options);
+
+  hbox = gimp_prop_enum_stock_box_new (config, "align-type", "gimp", 0, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+  gtk_widget_show (hbox);
+
+  label = gtk_label_new (_("Affect:"));
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+  gtk_box_reorder_child (GTK_BOX (hbox), label, 0);
+  gtk_widget_show (label);
+
+  return vbox;
+}
+
Index: gimp/app/tools/gimpalignoptions.h
===================================================================
RCS file: gimp/app/tools/gimpalignoptions.h
diff -N gimp/app/tools/gimpalignoptions.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gimp/app/tools/gimpalignoptions.h	23 Feb 2005 17:50:39 -0000
@@ -0,0 +1,50 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMP_ALIGN_OPTIONS_H__
+#define __GIMP_ALIGN_OPTIONS_H__
+
+
+#include "core/gimptooloptions.h"
+
+
+#define GIMP_TYPE_ALIGN_OPTIONS            (gimp_align_options_get_type ())
+#define GIMP_ALIGN_OPTIONS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_ALIGN_OPTIONS, GimpAlignOptions))
+#define GIMP_ALIGN_OPTIONS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_ALIGN_OPTIONS, GimpAlignOptionsClass))
+#define GIMP_IS_ALIGN_OPTIONS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_ALIGN_OPTIONS))
+#define GIMP_IS_ALIGN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_ALIGN_OPTIONS))
+#define GIMP_ALIGN_OPTIONS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_ALIGN_OPTIONS, GimpAlignOptionsClass))
+
+
+typedef struct _GimpAlignOptions      GimpAlignOptions;
+typedef struct _GimpToolOptionsClass GimpAlignOptionsClass;
+
+struct _GimpAlignOptions
+{
+  GimpToolOptions    parent_instence;
+
+  GimpTransformType  align_type;
+};
+
+
+GType       gimp_align_options_get_type (void) G_GNUC_CONST;
+
+GtkWidget * gimp_align_options_gui      (GimpToolOptions *tool_options);
+
+
+#endif /* __GIMP_ALIGN_OPTIONS_H__ */
Index: gimp/app/tools/gimpaligntool.c
===================================================================
RCS file: gimp/app/tools/gimpaligntool.c
diff -N gimp/app/tools/gimpaligntool.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gimp/app/tools/gimpaligntool.c	23 Feb 2005 17:50:39 -0000
@@ -0,0 +1,655 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "tools-types.h"
+
+#include "config/gimpdisplayconfig.h"
+#include "config/gimpguiconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpimage.h"
+#include "core/gimplayer.h"
+#include "core/gimplayermask.h"
+#include "core/gimplayer-floating-sel.h"
+#include "core/gimptoolinfo.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+#include "display/gimpdisplayshell-appearance.h"
+#include "display/gimpdisplayshell-draw.h"
+#include "display/gimpdisplayshell-transform.h"
+
+#include "widgets/gimphelp-ids.h"
+
+#include "gimpdrawtool.h"
+#include "gimpalignoptions.h"
+#include "gimpaligntool.h"
+#include "gimptoolcontrol.h"
+
+#include "gimp-intl.h"
+
+/*  local function prototypes  */
+
+static void   gimp_align_tool_class_init     (GimpAlignToolClass *klass);
+static void   gimp_align_tool_init           (GimpAlignTool      *align_tool);
+
+static gboolean gimp_align_tool_initialize   (GimpTool         *tool,
+                                              GimpDisplay      *gdisp);
+static void   gimp_align_tool_finalize       (GObject          *object);
+
+static void   gimp_align_tool_button_press   (GimpTool          *tool,
+                                             GimpCoords        *coords,
+                                             guint32            time,
+                                             GdkModifierType    state,
+                                             GimpDisplay       *gdisp);
+static void   gimp_align_tool_cursor_update  (GimpTool          *tool,
+                                             GimpCoords        *coords,
+                                             GdkModifierType    state,
+                                             GimpDisplay       *gdisp);
+
+static void   gimp_align_tool_draw           (GimpDrawTool      *draw_tool);
+
+static GtkWidget *button_with_stock          (GimpAlignmentType action,
+                                              GimpAlignTool   *align_tool);
+static GtkWidget *align_dialog               (GimpAlignTool   *align_tool);
+static void   set_action                     (GtkWidget       *widget,
+                                              gpointer         data);
+static void   do_horizontal_alignment        (GtkWidget       *widget,
+                                              gpointer         data);
+static void   do_vertical_alignment          (GtkWidget       *widget,
+                                              gpointer         data);
+
+static GimpDrawToolClass *parent_class = NULL;
+
+
+void
+gimp_align_tool_register (GimpToolRegisterCallback  callback,
+                         gpointer                  data)
+{
+  (* callback) (GIMP_TYPE_ALIGN_TOOL,
+                GIMP_TYPE_ALIGN_OPTIONS,
+                gimp_align_options_gui,
+                0,
+                "gimp-align-tool",
+                _("Align"),
+                _("Align layers & other items"),
+                N_("_Align"), "Q",
+                NULL, GIMP_HELP_TOOL_MOVE,
+                GIMP_STOCK_CENTER,
+                data);
+}
+
+GType
+gimp_align_tool_get_type (void)
+{
+  static GType tool_type = 0;
+
+  if (! tool_type)
+    {
+      static const GTypeInfo tool_info =
+      {
+        sizeof (GimpAlignToolClass),
+        (GBaseInitFunc) NULL,
+        (GBaseFinalizeFunc) NULL,
+        (GClassInitFunc) gimp_align_tool_class_init,
+        NULL,           /* class_finalize */
+        NULL,           /* class_data     */
+        sizeof (GimpAlignTool),
+        0,              /* n_preallocs    */
+        (GInstanceInitFunc) gimp_align_tool_init,
+      };
+
+      tool_type = g_type_register_static (GIMP_TYPE_DRAW_TOOL,
+                                          "GimpAlignTool",
+                                          &tool_info, 0);
+    }
+
+  return tool_type;
+}
+
+static void
+gimp_align_tool_class_init (GimpAlignToolClass *klass)
+{
+  GObjectClass      *object_class    = G_OBJECT_CLASS (klass);
+  GimpToolClass     *tool_class      = GIMP_TOOL_CLASS (klass);
+  GimpDrawToolClass *draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass);
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  object_class->finalize     = gimp_align_tool_finalize;
+
+  tool_class->initialize     = gimp_align_tool_initialize;
+  tool_class->button_press   = gimp_align_tool_button_press;
+  tool_class->cursor_update  = gimp_align_tool_cursor_update;
+
+  draw_tool_class->draw      = gimp_align_tool_draw;
+}
+
+static void
+gimp_align_tool_finalize (GObject *object)
+{
+  GimpTool      *tool       = GIMP_TOOL (object);
+  GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (object);
+
+  if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (object)))
+      gimp_draw_tool_stop (GIMP_DRAW_TOOL (object));
+
+  if (gimp_tool_control_is_active (tool->control))
+    gimp_tool_control_halt (tool->control);
+
+  if (align_tool->shell)
+    {
+      gtk_widget_destroy (align_tool->shell);
+      align_tool->shell       = NULL;
+    }
+
+  if (align_tool->reference_item)
+    g_object_remove_weak_pointer (G_OBJECT (align_tool->reference_item),
+                                  (gpointer) &align_tool->reference_item);
+
+  if (align_tool->target_item)
+    g_object_remove_weak_pointer (G_OBJECT (align_tool->target_item),
+                                  (gpointer) &align_tool->target_item);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+gimp_align_tool_initialize (GimpTool    *tool,
+                            GimpDisplay *gdisp)
+{
+  GimpAlignTool    *align_tool = GIMP_ALIGN_TOOL (tool);
+
+  /*  set gdisp so the dialog can be hidden on display destruction  */
+  tool->gdisp = gdisp;
+
+  if (! align_tool->shell)
+    align_tool->shell = align_dialog (align_tool);
+
+  return TRUE;
+}
+
+static void
+gimp_align_tool_init (GimpAlignTool *align_tool)
+{
+  GimpTool *tool = GIMP_TOOL (align_tool);
+
+  align_tool->target_item     = NULL;
+  align_tool->reference_item  = NULL;
+
+  align_tool->target_horz_align_type = GIMP_ALIGN_LEFT;
+  align_tool->ref_horz_align_type    = GIMP_ALIGN_LEFT;
+  align_tool->target_vert_align_type = GIMP_ALIGN_TOP;
+  align_tool->ref_vert_align_type    = GIMP_ALIGN_TOP;
+
+  align_tool->horz_offset = 0;
+  align_tool->vert_offset = 0;
+
+  align_tool->horz_offset_adjustment = NULL;
+  align_tool->vert_offset_adjustment = NULL;
+
+  gimp_tool_control_set_snap_to             (tool->control, FALSE);
+  gimp_tool_control_set_tool_cursor         (tool->control,
+                                             GIMP_TOOL_CURSOR_MOVE);
+
+}
+
+static void
+gimp_align_tool_button_press (GimpTool        *tool,
+                             GimpCoords      *coords,
+                             guint32          time,
+                             GdkModifierType  state,
+                             GimpDisplay     *gdisp)
+{
+  GimpAlignTool     *align    = GIMP_ALIGN_TOOL (tool);
+  GimpAlignOptions  *options  = GIMP_ALIGN_OPTIONS (tool->tool_info->tool_options);
+  GimpItem          *item     = NULL;
+
+  /*  If the tool was being used in another image...reset it  */
+
+  if (gimp_tool_control_is_active (tool->control))
+    {
+      if (gdisp != tool->gdisp)
+        {
+          gimp_draw_tool_stop (GIMP_DRAW_TOOL (tool));
+          gimp_tool_control_activate (tool->control);
+        }
+    }
+  else
+    {
+      gimp_tool_control_activate (tool->control);
+    }
+
+  tool->gdisp = gdisp;
+
+  if (!gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tool)))
+    gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), gdisp);
+
+  gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
+
+  if (options->align_type == GIMP_TRANSFORM_TYPE_PATH)
+    {
+      GimpVectors *vectors;
+
+      if (gimp_draw_tool_on_vectors (GIMP_DRAW_TOOL (tool), gdisp,
+                                     coords, 7, 7,
+                                     NULL, NULL, NULL, NULL, NULL,
+                                     &vectors))
+        {
+          item = GIMP_ITEM (vectors);
+        }
+    }
+  else if (options->align_type == GIMP_TRANSFORM_TYPE_LAYER)
+    {
+
+      GimpLayer *layer;
+
+      if ((layer = gimp_image_pick_correlate_layer (gdisp->gimage,
+                                                         coords->x,
+                                                         coords->y)))
+        {
+          item = GIMP_ITEM (layer);
+        }
+    }
+
+  if (item)
+    {
+      if (state & GDK_CONTROL_MASK)
+        {
+          if (align->reference_item)
+            g_object_remove_weak_pointer (G_OBJECT (align->reference_item),
+                                          (gpointer) &align->reference_item);
+          align->reference_item = item;
+          g_object_add_weak_pointer (G_OBJECT (align->reference_item),
+                                     (gpointer) &align->reference_item);
+        }
+      else
+        {
+          if (align->target_item)
+            g_object_remove_weak_pointer (G_OBJECT (align->target_item),
+                                          (gpointer) &align->target_item);
+          align->target_item = item;
+          g_object_add_weak_pointer (G_OBJECT (align->target_item),
+                                     (gpointer) &align->target_item);
+        }
+    }
+
+  gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
+}
+
+static void
+gimp_align_tool_cursor_update (GimpTool        *tool,
+                              GimpCoords      *coords,
+                              GdkModifierType  state,
+                              GimpDisplay     *gdisp)
+{
+  GimpAlignOptions  *options = GIMP_ALIGN_OPTIONS (tool->tool_info->tool_options);
+
+  GimpCursorType     cursor      = GIMP_CURSOR_BAD;
+  GimpToolCursorType tool_cursor = GIMP_TOOL_CURSOR_MOVE;
+  GimpCursorModifier modifier    = GIMP_CURSOR_MODIFIER_NONE;
+
+  if (options->align_type == GIMP_TRANSFORM_TYPE_PATH)
+    {
+      tool_cursor = GIMP_TOOL_CURSOR_PATHS;
+      modifier    = GIMP_CURSOR_MODIFIER_MOVE;
+
+      if (gimp_draw_tool_on_vectors (GIMP_DRAW_TOOL (tool), gdisp,
+                                     coords, 7, 7,
+                                     NULL, NULL, NULL, NULL, NULL, NULL))
+        {
+          cursor      = GDK_HAND2;
+          tool_cursor = GIMP_TOOL_CURSOR_HAND;
+        }
+    }
+  else
+    {
+      GimpLayer *layer;
+
+      if ((layer = gimp_image_pick_correlate_layer (gdisp->gimage,
+                                                         coords->x, coords->y)))
+	{
+	  /*  if there is a floating selection, and this aint it...  */
+	  if (gimp_image_floating_sel (gdisp->gimage) &&
+	      ! gimp_layer_is_floating_sel (layer))
+	    {
+              cursor      = GIMP_CURSOR_MOUSE;
+              tool_cursor = GIMP_TOOL_CURSOR_MOVE;
+              modifier    = GIMP_CURSOR_MODIFIER_ANCHOR;
+	    }
+	  else if (layer == gimp_image_get_active_layer (gdisp->gimage))
+	    {
+              cursor = GIMP_CURSOR_MOUSE;
+	    }
+	  else
+	    {
+              cursor      = GDK_HAND2;
+              tool_cursor = GIMP_TOOL_CURSOR_HAND;
+              modifier    = GIMP_CURSOR_MODIFIER_MOVE;
+	    }
+	}
+    }
+
+  gimp_tool_control_set_cursor          (tool->control, cursor);
+  gimp_tool_control_set_tool_cursor     (tool->control, tool_cursor);
+  gimp_tool_control_set_cursor_modifier (tool->control, modifier);
+
+  GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, gdisp);
+}
+
+static void
+gimp_align_tool_draw (GimpDrawTool *draw_tool)
+{
+  GimpAlignTool *align = GIMP_ALIGN_TOOL (draw_tool);
+  GimpItem      *item;
+
+  if ((item = align->target_item))
+    {
+      gimp_draw_tool_draw_rectangle (draw_tool, FALSE,
+                                     item->offset_x + 1, item->offset_y + 1,
+                                     item->width - 2, item->height - 2,
+                                     FALSE);
+    }
+
+  if ((item = align->reference_item))
+    {
+      gimp_draw_tool_draw_rectangle (draw_tool, FALSE,
+                                     item->offset_x, item->offset_y,
+                                     item->width, item->height,
+                                     FALSE);
+      gimp_draw_tool_draw_dashed_line (draw_tool,
+                                       item->offset_x,
+                                       item->offset_y,
+                                       item->offset_x + item->width,
+                                       item->offset_y + item->height,
+                                       FALSE);
+      gimp_draw_tool_draw_dashed_line (draw_tool,
+                                       item->offset_x,
+                                       item->offset_y + item->height,
+                                       item->offset_x + item->width,
+                                       item->offset_y,
+                                       FALSE);
+    }
+}
+
+
+static GtkWidget *
+align_dialog (GimpAlignTool *align_tool)
+{
+  GtkWidget         *dlg;
+  GtkWidget         *main_vbox;
+  GtkWidget         *table;
+  GtkWidget         *label;
+  GtkWidget         *button;
+  GtkWidget         *spinbutton;
+  gint               row, col;
+
+  dlg = gimp_dialog_new (_("Align Item"), "align",
+                         NULL, 0,
+                         gimp_standard_help_func, "gimp-item-align",
+                         NULL);
+
+  main_vbox = gtk_vbox_new (FALSE, 4);
+  gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 4);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), main_vbox,
+                      TRUE, TRUE, 0);
+  gtk_widget_show (main_vbox);
+
+  table = gtk_table_new (4, 9, FALSE);
+  gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 0);
+  gtk_widget_show (table);
+
+  gtk_table_set_row_spacings (GTK_TABLE (table), 10);
+  gtk_table_set_col_spacing (GTK_TABLE (table), 1, 20);
+  gtk_table_set_col_spacing (GTK_TABLE (table), 5, 20);
+
+  row = col = 0;
+
+  /* Top row */
+  label = gtk_label_new (_("Horizontal"));
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 2, 5, row, row + 1);
+  gtk_widget_show (label);
+
+  label = gtk_label_new (_("Vertical"));
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 6, 9, row, row + 1);
+  gtk_widget_show (label);
+
+  row++;
+
+  /* second row */
+
+  col = 2;
+
+  button = button_with_stock (GIMP_ALIGN_LEFT, align_tool);
+  gtk_table_attach_defaults (GTK_TABLE (table), button, col, col + 1, row, row + 1);
+  gimp_help_set_help_data (button, _("Align left edge of target"), NULL);
+  ++col;
+
+  button = button_with_stock (GIMP_ALIGN_CENTER, align_tool);
+  gtk_table_attach_defaults (GTK_TABLE (table), button, col, col + 1, row, row + 1);
+  gimp_help_set_help_data (button, _("Align center of target"), NULL);
+  ++col;
+
+  button = button_with_stock (GIMP_ALIGN_RIGHT, align_tool);
+  gtk_table_attach_defaults (GTK_TABLE (table), button, col, col + 1, row, row + 1);
+  gimp_help_set_help_data (button, _("Align right edge of target"), NULL);
+  ++col;
+
+  ++col;
+
+  button = button_with_stock (GIMP_ALIGN_TOP, align_tool);
+  gtk_table_attach_defaults (GTK_TABLE (table), button, col, col + 1, row, row + 1);
+  gimp_help_set_help_data (button, _("Align top edge of target"), NULL);
+  ++col;
+
+  button = button_with_stock (GIMP_ALIGN_MIDDLE, align_tool);
+  gtk_table_attach_defaults (GTK_TABLE (table), button, col, col + 1, row, row + 1);
+  gimp_help_set_help_data (button, _("Align middle of target"), NULL);
+  ++col;
+
+  button = button_with_stock (GIMP_ALIGN_BOTTOM, align_tool);
+  gtk_table_attach_defaults (GTK_TABLE (table), button, col, col + 1, row, row + 1);
+  gimp_help_set_help_data (button, _("Align bottom of target"), NULL);
+  ++col;
+
+  row++;
+
+  /* next row */
+  label = gtk_label_new (_("Offset"));
+  gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, row, row + 1);
+  gtk_widget_show (label);
+
+  spinbutton = gimp_spin_button_new (&align_tool->horz_offset_adjustment,
+                                     0,
+                                     -100000.,
+                                     100000.,
+                                     1., 20., 20., 1., 0);
+  gtk_table_attach_defaults (GTK_TABLE (table), spinbutton, 2, 5, row, row + 1);
+  g_signal_connect (align_tool->horz_offset_adjustment, "value-changed",
+                    G_CALLBACK (gimp_double_adjustment_update),
+                    &align_tool->horz_offset);
+  gtk_widget_show (spinbutton);
+
+  spinbutton = gimp_spin_button_new (&align_tool->vert_offset_adjustment,
+                                     0,
+                                     -100000.,
+                                     100000.,
+                                     1., 20., 20., 1., 0);
+  gtk_table_attach_defaults (GTK_TABLE (table), spinbutton, 6, 9, row, row + 1);
+  g_signal_connect (align_tool->vert_offset_adjustment, "value-changed",
+                    G_CALLBACK (gimp_double_adjustment_update),
+                    &align_tool->vert_offset);
+  gtk_widget_show (spinbutton);
+
+  row++;
+
+#if 0
+
+  /* next row */
+  button = gtk_button_new_with_label (_("Measure"));
+  gtk_table_attach_defaults (GTK_TABLE (table), button, 2, 5, row, row + 1);
+  gimp_help_set_help_data (button,
+                           _("Measure the horizontal offset between item and reference"),
+                           NULL);
+  gtk_widget_show (button);
+
+  button = gtk_button_new_with_label (_("Meaure"));
+  gtk_table_attach_defaults (GTK_TABLE (table), button, 6, 9, row, row + 1);
+  gimp_help_set_help_data (button,
+                           _("Measure the vertical offset between item and reference"),
+                           NULL);
+  gtk_widget_show (button);
+
+  ++row;
+
+#endif /* 0 */
+
+  gtk_widget_show (dlg);
+
+/*   gimp_dialog_run (GIMP_DIALOG (dlg)); */
+
+  return dlg;
+}
+
+
+static void
+do_horizontal_alignment (GtkWidget *widget,
+                         gpointer   data)
+{
+  GimpAlignTool *align_tool = data;
+
+  gimp_draw_tool_pause (GIMP_DRAW_TOOL (align_tool));
+
+  if (align_tool->target_item)
+    gimp_item_align (align_tool->target_item,
+                     align_tool->target_horz_align_type,
+                     align_tool->reference_item,
+                     align_tool->ref_horz_align_type,
+                     align_tool->horz_offset,
+                     TRUE);
+
+  gimp_image_flush (GIMP_TOOL (align_tool)->gdisp->gimage);
+
+  gimp_draw_tool_resume (GIMP_DRAW_TOOL (align_tool));
+}
+
+
+static void
+do_vertical_alignment (GtkWidget *widget,
+                       gpointer   data)
+{
+  GimpAlignTool *align_tool = data;
+
+  gimp_draw_tool_pause (GIMP_DRAW_TOOL (align_tool));
+
+  if (align_tool->target_item)
+    gimp_item_align (align_tool->target_item,
+                     align_tool->target_vert_align_type,
+                     align_tool->reference_item,
+                     align_tool->ref_vert_align_type,
+                     align_tool->vert_offset,
+                     TRUE);
+
+  gimp_image_flush (GIMP_TOOL (align_tool)->gdisp->gimage);
+
+  gimp_draw_tool_resume (GIMP_DRAW_TOOL (align_tool));
+}
+
+
+
+static GtkWidget *
+button_with_stock (GimpAlignmentType  action,
+                   GimpAlignTool     *align_tool)
+{
+  GtkWidget *button;
+  gchar     *stock_id;
+
+  switch (action)
+    {
+    case GIMP_ALIGN_LEFT:
+      stock_id = GIMP_STOCK_GRAVITY_WEST;
+      break;
+    case GIMP_ALIGN_CENTER:
+      stock_id = GIMP_STOCK_FLIP_HORIZONTAL;
+      break;
+    case GIMP_ALIGN_RIGHT:
+      stock_id = GIMP_STOCK_GRAVITY_EAST;
+      break;
+    case GIMP_ALIGN_TOP:
+      stock_id = GIMP_STOCK_GRAVITY_NORTH;
+      break;
+    case GIMP_ALIGN_MIDDLE:
+      stock_id = GIMP_STOCK_FLIP_VERTICAL;
+      break;
+    case GIMP_ALIGN_BOTTOM:
+      stock_id = GIMP_STOCK_GRAVITY_SOUTH;
+      break;
+    default:
+      stock_id = "?";
+      break;
+    }
+
+  button = gtk_button_new_from_stock (stock_id);
+
+  g_object_set_data (G_OBJECT (button), "action",       GINT_TO_POINTER (action));
+
+    g_signal_connect (button, "pressed",
+                      G_CALLBACK (set_action),
+                      align_tool);
+
+
+  gtk_widget_show (button);
+
+  return button;
+}
+
+static void
+set_action (GtkWidget *widget,
+            gpointer   data)
+{
+  GimpAlignTool      *align_tool    = data;
+  GimpAlignmentType   action;
+
+  action = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "action"));
+
+  switch (action)
+    {
+    case GIMP_ALIGN_LEFT:
+    case GIMP_ALIGN_CENTER:
+    case GIMP_ALIGN_RIGHT:
+      align_tool->ref_horz_align_type = action;
+      align_tool->target_horz_align_type = action;
+      do_horizontal_alignment (widget, data);
+      break;
+    case GIMP_ALIGN_TOP:
+    case GIMP_ALIGN_MIDDLE:
+    case GIMP_ALIGN_BOTTOM:
+      align_tool->ref_vert_align_type = action;
+      align_tool->target_vert_align_type = action;
+      do_vertical_alignment (widget, data);
+      break;
+    default:
+      break;
+    }
+}
Index: gimp/app/tools/gimpaligntool.h
===================================================================
RCS file: gimp/app/tools/gimpaligntool.h
diff -N gimp/app/tools/gimpaligntool.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gimp/app/tools/gimpaligntool.h	23 Feb 2005 17:50:39 -0000
@@ -0,0 +1,71 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMP_ALIGN_TOOL_H__
+#define __GIMP_ALIGN_TOOL_H__
+
+
+#include "gimpdrawtool.h"
+
+
+#define GIMP_TYPE_ALIGN_TOOL            (gimp_align_tool_get_type ())
+#define GIMP_ALIGN_TOOL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_ALIGN_TOOL, GimpAlignTool))
+#define GIMP_ALIGN_TOOL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_ALIGN_TOOL, GimpAlignToolClass))
+#define GIMP_IS_ALIGN_TOOL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_ALIGN_TOOL))
+#define GIMP_IS_ALIGN_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_ALIGN_TOOL))
+#define GIMP_ALIGN_TOOL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_ALIGN_TOOL, GimpAlignToolClass))
+
+
+typedef struct _GimpAlignTool      GimpAlignTool;
+typedef struct _GimpAlignToolClass GimpAlignToolClass;
+
+struct _GimpAlignTool
+{
+  GimpDrawTool         parent_instance;
+
+  GtkWidget           *shell;
+
+  GimpItem            *target_item;
+  GimpItem            *reference_item;
+
+  GimpAlignmentType    target_horz_align_type;
+  GimpAlignmentType    target_vert_align_type;
+  GimpAlignmentType    ref_horz_align_type;
+  GimpAlignmentType    ref_vert_align_type;
+
+  gdouble              horz_offset;
+  gdouble              vert_offset;
+
+  GtkObject           *horz_offset_adjustment;
+  GtkObject           *vert_offset_adjustment;
+
+};
+
+struct _GimpAlignToolClass
+{
+  GimpDrawToolClass parent_class;
+};
+
+
+void    gimp_align_tool_register (GimpToolRegisterCallback  callback,
+                                 gpointer                  data);
+
+GType   gimp_align_tool_get_type (void) G_GNUC_CONST;
+
+
+#endif  /*  __GIMP_ALIGN_TOOL_H__  */
