[gimp] app: rework the Align tool interaction taking multi-item selection into account.
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: rework the Align tool interaction taking multi-item selection into account.
- Date: Mon, 17 Oct 2022 17:06:28 +0000 (UTC)
commit 4eaf6c16b9f7b3ee610847b2ad6d601aa024b56e
Author: Jehan <jehan girinstud io>
Date: Thu Oct 13 17:47:01 2022 +0200
app: rework the Align tool interaction taking multi-item selection into account.
The old interaction was quite horrible. I don't think I ever really got a good
use of it. It was so hard to understand what you were picking and so on.
Now that we can multi-select items, let's just use this as the base of what we
want to align or distribute. Clicking on canvas will now mostly be used to pick
an item as reference. From now on, only the reference object will get on-canvas
handle, making it very obvious how your alignment or distribution will work.
I leave only an alternative picking method (with Alt or Shift-Alt pick) to add
guides to objects to align or distributes, as these don't have a selection
dockable.
I'm also improving the selection of stacked layers by looping through them
(similar as the layer selection on canvas feature) so that we can select even
background layers which have a lot of layers showing above.
I am planning to improve this tool even further, but this is a first step to
make it actually usable within the new multi-item interaction logic.
app/core/core-enums.c | 10 +-
app/core/core-enums.h | 9 +-
app/tools/gimpalignoptions.c | 482 +++++++++++++++++++++++++++++++++++++---
app/tools/gimpalignoptions.h | 30 ++-
app/tools/gimpaligntool.c | 514 +++++++++++++++++--------------------------
app/tools/gimpaligntool.h | 19 +-
6 files changed, 698 insertions(+), 366 deletions(-)
---
diff --git a/app/core/core-enums.c b/app/core/core-enums.c
index 235cd8c2ae..a50782242e 100644
--- a/app/core/core-enums.c
+++ b/app/core/core-enums.c
@@ -14,23 +14,17 @@ gimp_align_reference_type_get_type (void)
{
static const GEnumValue values[] =
{
- { GIMP_ALIGN_REFERENCE_FIRST, "GIMP_ALIGN_REFERENCE_FIRST", "first" },
{ GIMP_ALIGN_REFERENCE_IMAGE, "GIMP_ALIGN_REFERENCE_IMAGE", "image" },
{ GIMP_ALIGN_REFERENCE_SELECTION, "GIMP_ALIGN_REFERENCE_SELECTION", "selection" },
- { GIMP_ALIGN_REFERENCE_ACTIVE_LAYER, "GIMP_ALIGN_REFERENCE_ACTIVE_LAYER", "active-layer" },
- { GIMP_ALIGN_REFERENCE_ACTIVE_CHANNEL, "GIMP_ALIGN_REFERENCE_ACTIVE_CHANNEL", "active-channel" },
- { GIMP_ALIGN_REFERENCE_ACTIVE_PATH, "GIMP_ALIGN_REFERENCE_ACTIVE_PATH", "active-path" },
+ { GIMP_ALIGN_REFERENCE_PICK, "GIMP_ALIGN_REFERENCE_PICK", "pick" },
{ 0, NULL, NULL }
};
static const GimpEnumDesc descs[] =
{
- { GIMP_ALIGN_REFERENCE_FIRST, NC_("align-reference-type", "First item"), NULL },
{ GIMP_ALIGN_REFERENCE_IMAGE, NC_("align-reference-type", "Image"), NULL },
{ GIMP_ALIGN_REFERENCE_SELECTION, NC_("align-reference-type", "Selection"), NULL },
- { GIMP_ALIGN_REFERENCE_ACTIVE_LAYER, NC_("align-reference-type", "Active layer"), NULL },
- { GIMP_ALIGN_REFERENCE_ACTIVE_CHANNEL, NC_("align-reference-type", "Active channel"), NULL },
- { GIMP_ALIGN_REFERENCE_ACTIVE_PATH, NC_("align-reference-type", "Active path"), NULL },
+ { GIMP_ALIGN_REFERENCE_PICK, NC_("align-reference-type", "Picked reference object"), NULL },
{ 0, NULL, NULL }
};
diff --git a/app/core/core-enums.h b/app/core/core-enums.h
index cc6d64b179..350b6e26ff 100644
--- a/app/core/core-enums.h
+++ b/app/core/core-enums.h
@@ -42,12 +42,9 @@ GType gimp_align_reference_type_get_type (void) G_GNUC_CONST;
typedef enum /*< pdb-skip >*/
{
- GIMP_ALIGN_REFERENCE_FIRST, /*< desc="First item" >*/
- GIMP_ALIGN_REFERENCE_IMAGE, /*< desc="Image" >*/
- GIMP_ALIGN_REFERENCE_SELECTION, /*< desc="Selection" >*/
- GIMP_ALIGN_REFERENCE_ACTIVE_LAYER, /*< desc="Active layer" >*/
- GIMP_ALIGN_REFERENCE_ACTIVE_CHANNEL, /*< desc="Active channel" >*/
- GIMP_ALIGN_REFERENCE_ACTIVE_PATH /*< desc="Active path" >*/
+ GIMP_ALIGN_REFERENCE_IMAGE, /*< desc="Image" >*/
+ GIMP_ALIGN_REFERENCE_SELECTION, /*< desc="Selection" >*/
+ GIMP_ALIGN_REFERENCE_PICK, /*< desc="Picked reference object" >*/
} GimpAlignReferenceType;
diff --git a/app/tools/gimpalignoptions.c b/app/tools/gimpalignoptions.c
index 4787c4a27a..4d641c10b5 100644
--- a/app/tools/gimpalignoptions.c
+++ b/app/tools/gimpalignoptions.c
@@ -26,6 +26,16 @@
#include "tools-types.h"
+#include "core/gimp.h"
+#include "core/gimpguide.h"
+#include "core/gimpimage.h"
+#include "core/gimplayer.h"
+#include "core/gimpchannel.h"
+
+#include "vectors/gimpvectors.h"
+
+#include "widgets/gimpwidgets-utils.h"
+
#include "gimpalignoptions.h"
#include "gimptooloptions-gui.h"
@@ -43,21 +53,50 @@ enum
PROP_0,
PROP_ALIGN_REFERENCE,
PROP_OFFSET_X,
- PROP_OFFSET_Y
+ PROP_OFFSET_Y,
+ PROP_ALIGN_LAYERS,
+ PROP_ALIGN_VECTORS,
+};
+
+struct _GimpAlignOptionsPrivate
+{
+ gboolean align_layers;
+ gboolean align_vectors;
+
+ GList *selected_guides;
+ GObject *reference;
+
+ GtkWidget *selected_guides_label;
+ GtkWidget *reference_combo;
+ GtkWidget *reference_box;
+ GtkWidget *reference_label;
+ GtkWidget *button[ALIGN_OPTIONS_N_BUTTONS];
};
-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 void gimp_align_options_finalize (GObject *object);
+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 void gimp_align_options_image_changed (GimpContext *context,
+ GimpImage *image,
+ GimpAlignOptions *options);
-G_DEFINE_TYPE (GimpAlignOptions, gimp_align_options, GIMP_TYPE_TOOL_OPTIONS)
+static void gimp_align_options_update_area (GimpAlignOptions *options);
+static void gimp_align_options_guide_removed (GimpImage *image,
+ GimpGuide *guide,
+ GimpAlignOptions *options);
+static void gimp_align_options_reference_removed (GObject *object,
+ GimpAlignOptions *options);
+
+
+G_DEFINE_TYPE_WITH_PRIVATE (GimpAlignOptions, gimp_align_options, GIMP_TYPE_TOOL_OPTIONS)
#define parent_class gimp_selection_options_parent_class
@@ -69,6 +108,7 @@ gimp_align_options_class_init (GimpAlignOptionsClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gimp_align_options_finalize;
object_class->set_property = gimp_align_options_set_property;
object_class->get_property = gimp_align_options_get_property;
@@ -89,7 +129,7 @@ gimp_align_options_class_init (GimpAlignOptionsClass *klass)
_("Relative to"),
_("Reference image object a layer will be aligned on"),
GIMP_TYPE_ALIGN_REFERENCE_TYPE,
- GIMP_ALIGN_REFERENCE_FIRST,
+ GIMP_ALIGN_REFERENCE_IMAGE,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_OFFSET_X,
@@ -105,11 +145,37 @@ gimp_align_options_class_init (GimpAlignOptionsClass *klass)
_("Vertical offset for distribution"),
-GIMP_MAX_IMAGE_SIZE, GIMP_MAX_IMAGE_SIZE, 0,
GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ALIGN_LAYERS,
+ "align-layers",
+ _("Align or distribute selected layers"),
+ _("Selected layers will be aligned or distributed by the tool"),
+ TRUE,
+ GIMP_PARAM_STATIC_STRINGS);
+ GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ALIGN_VECTORS,
+ "align-vectors",
+ _("Align or distribute selected paths"),
+ _("Selected paths will be aligned or distributed by the tool"),
+ FALSE,
+ GIMP_PARAM_STATIC_STRINGS);
}
static void
gimp_align_options_init (GimpAlignOptions *options)
{
+ options->priv = gimp_align_options_get_instance_private (options);
+
+ options->priv->selected_guides = NULL;
+}
+
+static void
+gimp_align_options_finalize (GObject *object)
+{
+ GimpAlignOptions *options = GIMP_ALIGN_OPTIONS (object);
+
+ if (GIMP_CONTEXT (options)->gimp)
+ gimp_align_options_image_changed (gimp_get_user_context (GIMP_CONTEXT (options)->gimp),
+ NULL, options);
}
static void
@@ -124,16 +190,25 @@ gimp_align_options_set_property (GObject *object,
{
case PROP_ALIGN_REFERENCE:
options->align_reference = g_value_get_enum (value);
+ gimp_align_options_update_area (options);
break;
case PROP_OFFSET_X:
options->offset_x = g_value_get_double (value);
break;
-
case PROP_OFFSET_Y:
options->offset_y = g_value_get_double (value);
break;
+ case PROP_ALIGN_LAYERS:
+ options->priv->align_layers = g_value_get_boolean (value);
+ gimp_align_options_update_area (options);
+ break;
+ case PROP_ALIGN_VECTORS:
+ options->priv->align_vectors = g_value_get_boolean (value);
+ gimp_align_options_update_area (options);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -157,11 +232,17 @@ gimp_align_options_get_property (GObject *object,
case PROP_OFFSET_X:
g_value_set_double (value, options->offset_x);
break;
-
case PROP_OFFSET_Y:
g_value_set_double (value, options->offset_y);
break;
+ case PROP_ALIGN_LAYERS:
+ g_value_set_boolean (value, options->priv->align_layers);
+ break;
+ case PROP_ALIGN_VECTORS:
+ g_value_set_boolean (value, options->priv->align_vectors);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -268,14 +349,49 @@ gimp_align_options_gui (GimpToolOptions *tool_options)
GObject *config = G_OBJECT (tool_options);
GimpAlignOptions *options = GIMP_ALIGN_OPTIONS (tool_options);
GtkWidget *vbox = gimp_tool_options_gui (tool_options);
+ GtkWidget *widget;
GtkWidget *align_vbox;
GtkWidget *hbox;
GtkWidget *frame;
GtkWidget *label;
GtkWidget *spinbutton;
GtkWidget *combo;
+ gchar *text;
gint n = 0;
+ /* Selected objects */
+ widget = gimp_prop_check_button_new (config, "align-layers", NULL);
+ gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
+
+ widget = gimp_prop_check_button_new (config, "align-vectors", NULL);
+ gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
+
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+ gtk_widget_show (hbox);
+
+ widget = gtk_image_new_from_icon_name (GIMP_ICON_CURSOR, GTK_ICON_SIZE_BUTTON);
+ gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ /* TRANSLATORS: the %s strings are modifiers such as Shift, Alt or Cmd. */
+ text = g_strdup_printf (_("%s-pick guides to align or distribute (%s-%s for more)"),
+ gimp_get_mod_string (GDK_MOD1_MASK),
+ gimp_get_mod_string (gimp_get_extend_selection_mask ()),
+ gimp_get_mod_string (GDK_MOD1_MASK));
+ widget = gtk_label_new (text);
+ gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
+ gtk_label_set_line_wrap_mode (GTK_LABEL (widget), PANGO_WRAP_WORD);
+ g_free (text);
+ gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ widget = gtk_label_new (NULL);
+ gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+ options->priv->selected_guides_label = widget;
+
+ /* Align frame */
frame = gimp_frame_new (_("Align"));
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
@@ -288,20 +404,41 @@ gimp_align_options_gui (GimpToolOptions *tool_options)
gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo), _("Relative to"));
g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
gtk_box_pack_start (GTK_BOX (align_vbox), combo, FALSE, FALSE, 0);
+ options->priv->reference_combo = combo;
+
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_box_pack_start (GTK_BOX (align_vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
+ options->priv->reference_box = hbox;
+
+ widget = gtk_image_new_from_icon_name (GIMP_ICON_CURSOR, GTK_ICON_SIZE_BUTTON);
+ gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ widget = gtk_label_new (_("Select the reference object"));
+ gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
- options->button[n++] =
+ widget = gtk_label_new (NULL);
+ gtk_box_pack_start (GTK_BOX (align_vbox), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+ options->priv->reference_label = widget;
+
+
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+ gtk_box_pack_start (GTK_BOX (align_vbox), hbox, FALSE, FALSE, 0);
+ gtk_widget_show (hbox);
+
+ options->priv->button[n++] =
gimp_align_options_button_new (options, GIMP_ALIGN_LEFT, hbox,
_("Align left edge of target"));
- options->button[n++] =
+ options->priv->button[n++] =
gimp_align_options_button_new (options, GIMP_ALIGN_HCENTER, hbox,
_("Align center of target"));
- options->button[n++] =
+ options->priv->button[n++] =
gimp_align_options_button_new (options, GIMP_ALIGN_RIGHT, hbox,
_("Align right edge of target"));
@@ -309,18 +446,19 @@ gimp_align_options_gui (GimpToolOptions *tool_options)
gtk_box_pack_start (GTK_BOX (align_vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
- options->button[n++] =
+ options->priv->button[n++] =
gimp_align_options_button_new (options, GIMP_ALIGN_TOP, hbox,
_("Align top edge of target"));
- options->button[n++] =
+ options->priv->button[n++] =
gimp_align_options_button_new (options, GIMP_ALIGN_VCENTER, hbox,
_("Align middle of target"));
- options->button[n++] =
+ options->priv->button[n++] =
gimp_align_options_button_new (options, GIMP_ALIGN_BOTTOM, hbox,
_("Align bottom of target"));
+ /* Distribute frame */
frame = gimp_frame_new (_("Distribute"));
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
@@ -333,19 +471,19 @@ gimp_align_options_gui (GimpToolOptions *tool_options)
gtk_box_pack_start (GTK_BOX (align_vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
- options->button[n++] =
+ options->priv->button[n++] =
gimp_align_options_button_new (options, GIMP_ARRANGE_LEFT, hbox,
_("Distribute left edges of targets"));
- options->button[n++] =
+ options->priv->button[n++] =
gimp_align_options_button_new (options, GIMP_ARRANGE_HCENTER, hbox,
_("Distribute horizontal centers of targets"));
- options->button[n++] =
+ options->priv->button[n++] =
gimp_align_options_button_new (options, GIMP_ARRANGE_RIGHT, hbox,
_("Distribute right edges of targets"));
- options->button[n++] =
+ options->priv->button[n++] =
gimp_align_options_button_new (options, GIMP_ARRANGE_HFILL, hbox,
_("Distribute targets evenly in the horizontal"));
@@ -353,19 +491,19 @@ gimp_align_options_gui (GimpToolOptions *tool_options)
gtk_box_pack_start (GTK_BOX (align_vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
- options->button[n++] =
+ options->priv->button[n++] =
gimp_align_options_button_new (options, GIMP_ARRANGE_TOP, hbox,
_("Distribute top edges of targets"));
- options->button[n++] =
+ options->priv->button[n++] =
gimp_align_options_button_new (options, GIMP_ARRANGE_VCENTER, hbox,
_("Distribute vertical centers of targets"));
- options->button[n++] =
+ options->priv->button[n++] =
gimp_align_options_button_new (options, GIMP_ARRANGE_BOTTOM, hbox,
_("Distribute bottoms of targets"));
- options->button[n++] =
+ options->priv->button[n++] =
gimp_align_options_button_new (options, GIMP_ARRANGE_VFILL, hbox,
_("Distribute targets evenly in the vertical"));
@@ -393,5 +531,295 @@ gimp_align_options_gui (GimpToolOptions *tool_options)
1, 20, 0);
gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
+ g_signal_connect (gimp_get_user_context (GIMP_CONTEXT (options)->gimp),
+ "image-changed",
+ G_CALLBACK (gimp_align_options_image_changed),
+ tool_options);
+ gimp_align_options_image_changed (gimp_get_user_context (GIMP_CONTEXT (options)->gimp),
+ gimp_context_get_image (gimp_get_user_context (GIMP_CONTEXT
(options)->gimp)),
+ options);
+
return vbox;
}
+
+GList *
+gimp_align_options_get_objects (GimpAlignOptions *options)
+{
+ GimpImage *image;
+ GList *objects = NULL;
+
+ image = gimp_context_get_image (gimp_get_user_context (GIMP_CONTEXT (options)->gimp));
+
+ if (image)
+ {
+ if (options->priv->align_layers)
+ {
+ GList *layers;
+
+ layers = gimp_image_get_selected_layers (image);
+ layers = g_list_copy (layers);
+ objects = g_list_concat (objects, layers);
+ }
+ if (options->priv->align_vectors)
+ {
+ GList *vectors;
+
+ vectors = gimp_image_get_selected_vectors (image);
+ vectors = g_list_copy (vectors);
+ objects = g_list_concat (objects, vectors);
+ }
+
+ if (options->priv->selected_guides)
+ {
+ GList *guides;
+
+ guides = g_list_copy (options->priv->selected_guides);
+ objects = g_list_concat (objects, guides);
+ }
+ }
+
+ return objects;
+}
+
+void
+gimp_align_options_pick_reference (GimpAlignOptions *options,
+ GObject *object)
+{
+ if (options->priv->reference)
+ g_signal_handlers_disconnect_by_func (options->priv->reference,
+ G_CALLBACK (gimp_align_options_reference_removed),
+ options);
+
+ g_clear_object (&options->priv->reference);
+
+ if (object)
+ {
+ options->priv->reference = g_object_ref (object);
+
+ /* Both GimpItem and GimpGuide/GimpAuxItem have a "removed" signal with
+ * similar signature. */
+ g_signal_connect_object (options->priv->reference,
+ "removed",
+ G_CALLBACK (gimp_align_options_reference_removed),
+ options, 0);
+ }
+
+ gimp_align_options_update_area (options);
+}
+
+GObject *
+gimp_align_options_get_reference (GimpAlignOptions *options,
+ gboolean blink_if_none)
+{
+ GObject *reference = NULL;
+ GimpImage *image;
+
+ image = gimp_context_get_image (gimp_get_user_context (GIMP_CONTEXT (options)->gimp));
+
+ if (image)
+ {
+ switch (options->align_reference)
+ {
+ case GIMP_ALIGN_REFERENCE_IMAGE:
+ reference = G_OBJECT (image);
+ break;
+ case GIMP_ALIGN_REFERENCE_SELECTION:
+ reference = G_OBJECT (gimp_image_get_mask (image));
+ break;
+ case GIMP_ALIGN_REFERENCE_PICK:
+ reference = G_OBJECT (options->priv->reference);
+ break;
+ }
+
+ if (reference == NULL && blink_if_none)
+ {
+ if (options->align_reference == GIMP_ALIGN_REFERENCE_PICK)
+ gimp_widget_blink (options->priv->reference_box);
+ else
+ gimp_widget_blink (options->priv->reference_combo);
+ }
+ }
+
+ return reference;
+}
+
+void
+gimp_align_options_pick_guide (GimpAlignOptions *options,
+ GimpGuide *guide,
+ gboolean extend)
+{
+ if (! extend)
+ g_clear_pointer (&options->priv->selected_guides, g_list_free);
+
+ if (guide)
+ {
+ GList *list;
+
+ if ((list = g_list_find (options->priv->selected_guides, guide)))
+ options->priv->selected_guides = g_list_delete_link (options->priv->selected_guides, list);
+ else
+ options->priv->selected_guides = g_list_prepend (options->priv->selected_guides, guide);
+ }
+
+ gimp_align_options_update_area (options);
+}
+
+
+/* Private functions */
+
+static void
+gimp_align_options_image_changed (GimpContext *context,
+ GimpImage *image,
+ GimpAlignOptions *options)
+{
+ GimpImage *prev_image;
+
+ prev_image = g_object_get_data (G_OBJECT (options), "gimp-align-options-image");
+
+ if (image != prev_image)
+ {
+ /* We cannot keep track of selected guides across image changes. */
+ g_clear_pointer (&options->priv->selected_guides, g_list_free);
+ gimp_align_options_pick_reference (options, NULL);
+
+ if (prev_image)
+ {
+ g_signal_handlers_disconnect_by_func (prev_image,
+ G_CALLBACK (gimp_align_options_update_area),
+ options);
+ g_signal_handlers_disconnect_by_func (prev_image,
+ G_CALLBACK (gimp_align_options_guide_removed),
+ options);
+ }
+ if (image)
+ {
+ g_signal_connect_object (image, "selected-channels-changed",
+ G_CALLBACK (gimp_align_options_update_area),
+ options, G_CONNECT_SWAPPED);
+ g_signal_connect_object (image, "selected-layers-changed",
+ G_CALLBACK (gimp_align_options_update_area),
+ options, G_CONNECT_SWAPPED);
+ g_signal_connect_object (image, "guide-removed",
+ G_CALLBACK (gimp_align_options_guide_removed),
+ options, 0);
+ }
+
+ g_object_set_data (G_OBJECT (options), "gimp-align-options-image", image);
+ gimp_align_options_update_area (options);
+ }
+}
+
+static void
+gimp_align_options_update_area (GimpAlignOptions *options)
+{
+ GimpImage *image;
+ GList *layers = NULL;
+ GList *vectors = NULL;
+ gint n_items = 0;
+ gchar *text;
+
+ image = gimp_context_get_image (gimp_get_user_context (GIMP_CONTEXT (options)->gimp));
+
+ /* GUI not created yet. */
+ if (! options->priv->reference_combo)
+ return;
+
+ if (image)
+ {
+ layers = gimp_image_get_selected_layers (image);
+ vectors = gimp_image_get_selected_vectors (image);
+
+ if (options->priv->align_layers)
+ n_items += g_list_length (layers);
+ if (options->priv->align_vectors)
+ n_items += g_list_length (vectors);
+
+ n_items += g_list_length (options->priv->selected_guides);
+ }
+
+ for (gint i = 0; i < ALIGN_OPTIONS_N_BUTTONS; i++)
+ {
+ if (options->priv->button[i])
+ gtk_widget_set_sensitive (options->priv->button[i], n_items > 0);
+ }
+
+ /* Update the guide picking widgets. */
+ if (options->priv->selected_guides)
+ {
+ gchar *tmp_txt;
+
+ tmp_txt = g_strdup_printf (ngettext ("1 guide will be aligned or distributed",
+ "%d guides will be aligned or distributed",
+ g_list_length (options->priv->selected_guides)),
+ g_list_length (options->priv->selected_guides));
+ text = g_strdup_printf ("<i>%s</i>", tmp_txt);
+ g_free (tmp_txt);
+ gtk_widget_show (options->priv->selected_guides_label);
+ }
+ else
+ {
+ text = NULL;
+ gtk_widget_hide (options->priv->selected_guides_label);
+ }
+
+ gtk_label_set_markup (GTK_LABEL (options->priv->selected_guides_label), text);
+ g_free (text);
+
+ /* Update the reference widgets. */
+ text = NULL;
+ if (options->align_reference == GIMP_ALIGN_REFERENCE_PICK)
+ {
+ if (options->priv->reference)
+ {
+ gchar *tmp_txt;
+
+ if (GIMP_IS_LAYER (options->priv->reference))
+ tmp_txt = g_strdup_printf (_("Reference layer: %s"),
+ gimp_object_get_name (options->priv->reference));
+ else if (GIMP_IS_CHANNEL (options->priv->reference))
+ tmp_txt = g_strdup_printf (_("Reference channel: %s"),
+ gimp_object_get_name (options->priv->reference));
+ else if (GIMP_IS_VECTORS (options->priv->reference))
+ tmp_txt = g_strdup_printf (_("Reference path: %s"),
+ gimp_object_get_name (options->priv->reference));
+ else if (GIMP_IS_GUIDE (options->priv->reference))
+ tmp_txt = g_strdup (_("Reference guide"));
+ else
+ g_return_if_reached ();
+
+ text = g_strdup_printf ("<i>%s</i>", tmp_txt);
+ g_free (tmp_txt);
+ }
+ gtk_widget_show (options->priv->reference_box);
+ }
+ else
+ {
+ gtk_widget_hide (options->priv->reference_box);
+ }
+ gtk_label_set_markup (GTK_LABEL (options->priv->reference_label), text);
+ g_free (text);
+}
+
+static void
+gimp_align_options_guide_removed (GimpImage *image,
+ GimpGuide *guide,
+ GimpAlignOptions *options)
+{
+ GList *list;
+
+ if ((list = g_list_find (options->priv->selected_guides, guide)))
+ options->priv->selected_guides = g_list_delete_link (options->priv->selected_guides, list);
+
+ if (G_OBJECT (guide) == options->priv->reference)
+ gimp_align_options_pick_reference (options, NULL);
+
+ gimp_align_options_update_area (options);
+}
+
+static void
+gimp_align_options_reference_removed (GObject *object,
+ GimpAlignOptions *options)
+{
+ if (G_OBJECT (object) == options->priv->reference)
+ gimp_align_options_pick_reference (options, NULL);
+}
diff --git a/app/tools/gimpalignoptions.h b/app/tools/gimpalignoptions.h
index 5d4fe047ed..45cac97ed0 100644
--- a/app/tools/gimpalignoptions.h
+++ b/app/tools/gimpalignoptions.h
@@ -33,18 +33,19 @@
#define GIMP_ALIGN_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_ALIGN_OPTIONS,
GimpAlignOptionsClass))
-typedef struct _GimpAlignOptions GimpAlignOptions;
-typedef struct _GimpAlignOptionsClass GimpAlignOptionsClass;
+typedef struct _GimpAlignOptions GimpAlignOptions;
+typedef struct _GimpAlignOptionsPrivate GimpAlignOptionsPrivate;
+typedef struct _GimpAlignOptionsClass GimpAlignOptionsClass;
struct _GimpAlignOptions
{
- GimpToolOptions parent_instance;
+ GimpToolOptions parent_instance;
- GimpAlignReferenceType align_reference;
- gdouble offset_x;
- gdouble offset_y;
+ GimpAlignReferenceType align_reference;
+ gdouble offset_x;
+ gdouble offset_y;
- GtkWidget *button[ALIGN_OPTIONS_N_BUTTONS];
+ GimpAlignOptionsPrivate *priv;
};
struct _GimpAlignOptionsClass
@@ -56,9 +57,20 @@ struct _GimpAlignOptionsClass
};
-GType gimp_align_options_get_type (void) G_GNUC_CONST;
+GType gimp_align_options_get_type (void) G_GNUC_CONST;
-GtkWidget * gimp_align_options_gui (GimpToolOptions *tool_options);
+GtkWidget * gimp_align_options_gui (GimpToolOptions *tool_options);
+
+GList * gimp_align_options_get_objects (GimpAlignOptions *options);
+
+void gimp_align_options_pick_reference (GimpAlignOptions *options,
+ GObject *object);
+GObject * gimp_align_options_get_reference (GimpAlignOptions *options,
+ gboolean blink_if_none);
+
+void gimp_align_options_pick_guide (GimpAlignOptions *options,
+ GimpGuide *guide,
+ gboolean extend);
#endif /* __GIMP_ALIGN_OPTIONS_H__ */
diff --git a/app/tools/gimpaligntool.c b/app/tools/gimpaligntool.c
index 469899321c..7fcfaf0b76 100644
--- a/app/tools/gimpaligntool.c
+++ b/app/tools/gimpaligntool.c
@@ -101,10 +101,6 @@ static void gimp_align_tool_draw (GimpDrawTool *draw_tool
static void gimp_align_tool_align (GimpAlignTool *align_tool,
GimpAlignmentType align_type);
-static void gimp_align_tool_object_removed (GObject *object,
- GimpAlignTool *align_tool);
-static void gimp_align_tool_clear_selected (GimpAlignTool *align_tool);
-
G_DEFINE_TYPE (GimpAlignTool, gimp_align_tool, GIMP_TYPE_DRAW_TOOL)
@@ -158,7 +154,7 @@ gimp_align_tool_init (GimpAlignTool *align_tool)
GIMP_CURSOR_PRECISION_PIXEL_BORDER);
gimp_tool_control_set_tool_cursor (tool->control, GIMP_TOOL_CURSOR_MOVE);
- align_tool->function = ALIGN_TOOL_IDLE;
+ align_tool->function = ALIGN_TOOL_REF_IDLE;
}
static void
@@ -181,8 +177,6 @@ gimp_align_tool_control (GimpTool *tool,
GimpToolAction action,
GimpDisplay *display)
{
- GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (tool);
-
switch (action)
{
case GIMP_TOOL_ACTION_PAUSE:
@@ -190,7 +184,6 @@ gimp_align_tool_control (GimpTool *tool,
break;
case GIMP_TOOL_ACTION_HALT:
- gimp_align_tool_clear_selected (align_tool);
break;
case GIMP_TOOL_ACTION_COMMIT:
@@ -246,10 +239,8 @@ gimp_align_tool_button_release (GimpTool *tool,
GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (tool);
GimpAlignOptions *options = GIMP_ALIGN_TOOL_GET_OPTIONS (tool);
GimpDisplayShell *shell = gimp_display_get_shell (display);
- GObject *object = NULL;
GimpImage *image = gimp_display_get_image (display);
GdkModifierType extend_mask;
- gint i;
extend_mask = gimp_get_extend_selection_mask ();
@@ -266,108 +257,99 @@ gimp_align_tool_button_release (GimpTool *tool,
return;
}
- if (! (state & extend_mask)) /* start a new list */
+ if (state & GDK_MOD1_MASK)
{
- gimp_align_tool_clear_selected (align_tool);
- align_tool->set_reference = FALSE;
- }
+ GimpGuide *guide = NULL;
- /* if mouse has moved less than EPSILON pixels since button press,
- * select the nearest thing, otherwise make a rubber-band rectangle
- */
- if (hypot (coords->x - align_tool->x1,
- coords->y - align_tool->y1) < EPSILON)
- {
- GimpVectors *vectors;
- GimpGuide *guide;
- GimpLayer *layer;
- gint snap_distance = display->config->snap_distance;
-
- if ((vectors = gimp_image_pick_vectors (image,
- coords->x, coords->y,
- FUNSCALEX (shell, snap_distance),
- FUNSCALEY (shell, snap_distance))))
- {
- object = G_OBJECT (vectors);
- }
- else if (gimp_display_shell_get_show_guides (shell) &&
- (guide = gimp_image_pick_guide (image,
- coords->x, coords->y,
- FUNSCALEX (shell, snap_distance),
- FUNSCALEY (shell, snap_distance))))
+ if (gimp_display_shell_get_show_guides (shell))
{
- object = G_OBJECT (guide);
- }
- else if ((layer = gimp_image_pick_layer_by_bounds (image,
- coords->x, coords->y)))
- {
- object = G_OBJECT (layer);
- }
+ gint snap_distance = display->config->snap_distance;
- if (object)
- {
- if (! g_list_find (align_tool->selected_objects, object))
- {
- align_tool->selected_objects =
- g_list_append (align_tool->selected_objects, object);
-
- g_signal_connect (object, "removed",
- G_CALLBACK (gimp_align_tool_object_removed),
- align_tool);
-
- /* if an object has been selected using unmodified click,
- * it should be used as the reference
- */
- if (! (state & extend_mask))
- align_tool->set_reference = TRUE;
- }
+ guide = gimp_image_pick_guide (image,
+ coords->x, coords->y,
+ FUNSCALEX (shell, snap_distance),
+ FUNSCALEY (shell, snap_distance));
}
+
+ gimp_align_options_pick_guide (options, guide, (gboolean) state & extend_mask);
}
- else /* FIXME: look for vectors too */
+ else
{
- gint X0 = MIN (coords->x, align_tool->x1);
- gint X1 = MAX (coords->x, align_tool->x1);
- gint Y0 = MIN (coords->y, align_tool->y1);
- gint Y1 = MAX (coords->y, align_tool->y1);
- GList *all_layers;
- GList *list;
-
- all_layers = gimp_image_get_layer_list (image);
-
- for (list = all_layers; list; list = g_list_next (list))
+ GObject *object = NULL;
+
+ /* Check if a layer is fully included in the rubber-band rectangle.
+ * Don't verify for too small rectangles.
+ */
+ /* FIXME: look for vectors too */
+ if (hypot (coords->x - align_tool->x1,
+ coords->y - align_tool->y1) > EPSILON)
{
- GimpLayer *layer = list->data;
- gint x0, y0, x1, y1;
+ gint X0 = MIN (coords->x, align_tool->x1);
+ gint X1 = MAX (coords->x, align_tool->x1);
+ gint Y0 = MIN (coords->y, align_tool->y1);
+ gint Y1 = MAX (coords->y, align_tool->y1);
+ GList *all_layers;
+ GList *list;
- if (! gimp_item_get_visible (GIMP_ITEM (layer)))
- continue;
+ all_layers = gimp_image_get_layer_list (image);
- gimp_item_get_offset (GIMP_ITEM (layer), &x0, &y0);
- x1 = x0 + gimp_item_get_width (GIMP_ITEM (layer));
- y1 = y0 + gimp_item_get_height (GIMP_ITEM (layer));
+ for (list = all_layers; list; list = g_list_next (list))
+ {
+ GimpLayer *layer = list->data;
+ gint x0, y0, x1, y1;
+
+ if (! gimp_item_get_visible (GIMP_ITEM (layer)))
+ continue;
- if (x0 < X0 || y0 < Y0 || x1 > X1 || y1 > Y1)
- continue;
+ gimp_item_get_offset (GIMP_ITEM (layer), &x0, &y0);
+ x1 = x0 + gimp_item_get_width (GIMP_ITEM (layer));
+ y1 = y0 + gimp_item_get_height (GIMP_ITEM (layer));
- if (g_list_find (align_tool->selected_objects, layer))
- continue;
+ if (x0 < X0 || y0 < Y0 || x1 > X1 || y1 > Y1)
+ continue;
- align_tool->selected_objects =
- g_list_append (align_tool->selected_objects, layer);
+ object = G_OBJECT (layer);
+ break;
+ }
- g_signal_connect (layer, "removed",
- G_CALLBACK (gimp_align_tool_object_removed),
- align_tool);
+ g_list_free (all_layers);
}
- g_list_free (all_layers);
- }
+ if (object == NULL)
+ {
+ GimpVectors *vectors;
+ GimpGuide *guide;
+ GimpLayer *layer;
+ GObject *previously_picked;
+ gint snap_distance = display->config->snap_distance;
- for (i = 0; i < ALIGN_OPTIONS_N_BUTTONS; i++)
- {
- if (options->button[i])
- gtk_widget_set_sensitive (options->button[i],
- align_tool->selected_objects != NULL);
+ previously_picked = gimp_align_options_get_reference (options, FALSE);
+
+
+ if ((vectors = gimp_image_pick_vectors (image,
+ coords->x, coords->y,
+ FUNSCALEX (shell, snap_distance),
+ FUNSCALEY (shell, snap_distance))))
+ {
+ object = G_OBJECT (vectors);
+ }
+ else if (gimp_display_shell_get_show_guides (shell) &&
+ (guide = gimp_image_pick_guide (image,
+ coords->x, coords->y,
+ FUNSCALEX (shell, snap_distance),
+ FUNSCALEY (shell, snap_distance))))
+ {
+ object = G_OBJECT (guide);
+ }
+ else if ((layer = gimp_image_pick_layer (image, coords->x, coords->y,
+ previously_picked && GIMP_IS_LAYER (previously_picked)?
GIMP_LAYER (previously_picked) : NULL)))
+ {
+ object = G_OBJECT (layer);
+ }
+ }
+
+ if (object)
+ gimp_align_options_pick_reference (options, object);
}
align_tool->x2 = align_tool->x1;
@@ -422,23 +404,22 @@ gimp_align_tool_oper_update (GimpTool *tool,
GimpDisplay *display)
{
GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (tool);
+ GimpAlignOptions *options = GIMP_ALIGN_TOOL_GET_OPTIONS (align_tool);
GimpDisplayShell *shell = gimp_display_get_shell (display);
GimpImage *image = gimp_display_get_image (display);
gint snap_distance = display->config->snap_distance;
- gboolean add;
- add = ((state & gimp_get_extend_selection_mask ()) &&
- align_tool->selected_objects);
+ state &= gimp_get_all_modifiers_mask ();
+
+ align_tool->function = ALIGN_TOOL_NO_ACTION;
if (gimp_image_pick_vectors (image,
coords->x, coords->y,
FUNSCALEX (shell, snap_distance),
FUNSCALEY (shell, snap_distance)))
{
- if (add)
- align_tool->function = ALIGN_TOOL_ADD_PATH;
- else
- align_tool->function = ALIGN_TOOL_PICK_PATH;
+ if (options->align_reference == GIMP_ALIGN_REFERENCE_PICK)
+ align_tool->function = ALIGN_TOOL_REF_PICK_PATH;
}
else if (gimp_display_shell_get_show_guides (shell) &&
gimp_image_pick_guide (image,
@@ -446,21 +427,24 @@ gimp_align_tool_oper_update (GimpTool *tool,
FUNSCALEX (shell, snap_distance),
FUNSCALEY (shell, snap_distance)))
{
- if (add)
- align_tool->function = ALIGN_TOOL_ADD_GUIDE;
- else
- align_tool->function = ALIGN_TOOL_PICK_GUIDE;
+ if (state == (gimp_get_extend_selection_mask () | GDK_MOD1_MASK))
+ align_tool->function = ALIGN_TOOL_ALIGN_ADD_GUIDE;
+ else if (state == GDK_MOD1_MASK)
+ align_tool->function = ALIGN_TOOL_ALIGN_PICK_GUIDE;
+ else if (options->align_reference == GIMP_ALIGN_REFERENCE_PICK)
+ align_tool->function = ALIGN_TOOL_REF_PICK_GUIDE;
}
else if (gimp_image_pick_layer_by_bounds (image, coords->x, coords->y))
{
- if (add)
- align_tool->function = ALIGN_TOOL_ADD_LAYER;
- else
- align_tool->function = ALIGN_TOOL_PICK_LAYER;
+ if (options->align_reference == GIMP_ALIGN_REFERENCE_PICK)
+ align_tool->function = ALIGN_TOOL_REF_PICK_LAYER;
}
else
{
- align_tool->function = ALIGN_TOOL_IDLE;
+ if (state & GDK_MOD1_MASK)
+ align_tool->function = ALIGN_TOOL_ALIGN_IDLE;
+ else if (options->align_reference == GIMP_ALIGN_REFERENCE_PICK)
+ align_tool->function = ALIGN_TOOL_REF_IDLE;
}
gimp_align_tool_status_update (tool, display, state, proximity);
@@ -476,32 +460,30 @@ gimp_align_tool_cursor_update (GimpTool *tool,
GimpToolCursorType tool_cursor = GIMP_TOOL_CURSOR_NONE;
GimpCursorModifier modifier = GIMP_CURSOR_MODIFIER_NONE;
- /* always add '+' when Shift is pressed, even if nothing is selected */
- if (state & gimp_get_extend_selection_mask ())
- modifier = GIMP_CURSOR_MODIFIER_PLUS;
-
switch (align_tool->function)
{
- case ALIGN_TOOL_IDLE:
+ case ALIGN_TOOL_REF_IDLE:
+ case ALIGN_TOOL_ALIGN_IDLE:
tool_cursor = GIMP_TOOL_CURSOR_RECT_SELECT;
break;
- case ALIGN_TOOL_PICK_LAYER:
- case ALIGN_TOOL_ADD_LAYER:
+ case ALIGN_TOOL_REF_PICK_LAYER:
tool_cursor = GIMP_TOOL_CURSOR_HAND;
break;
- case ALIGN_TOOL_PICK_GUIDE:
- case ALIGN_TOOL_ADD_GUIDE:
+ case ALIGN_TOOL_ALIGN_ADD_GUIDE:
+ modifier = GIMP_CURSOR_MODIFIER_PLUS;
+ case ALIGN_TOOL_REF_PICK_GUIDE:
+ case ALIGN_TOOL_ALIGN_PICK_GUIDE:
tool_cursor = GIMP_TOOL_CURSOR_MOVE;
break;
- case ALIGN_TOOL_PICK_PATH:
- case ALIGN_TOOL_ADD_PATH:
+ case ALIGN_TOOL_REF_PICK_PATH:
tool_cursor = GIMP_TOOL_CURSOR_PATHS;
break;
- case ALIGN_TOOL_DRAG_BOX:
+ case ALIGN_TOOL_REF_DRAG_BOX:
+ case ALIGN_TOOL_NO_ACTION:
break;
}
@@ -518,8 +500,9 @@ gimp_align_tool_status_update (GimpTool *tool,
GdkModifierType state,
gboolean proximity)
{
- GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (tool);
- GdkModifierType extend_mask;
+ GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (tool);
+ gchar *status = NULL;
+ GdkModifierType extend_mask;
extend_mask = gimp_get_extend_selection_mask ();
@@ -527,75 +510,59 @@ gimp_align_tool_status_update (GimpTool *tool,
if (proximity)
{
- gchar *status = NULL;
-
- if (! align_tool->selected_objects)
- {
- /* no need to suggest Shift if nothing is selected */
- state |= extend_mask;
- }
-
switch (align_tool->function)
{
- case ALIGN_TOOL_IDLE:
- status = gimp_suggest_modifiers (_("Click on a layer, path or guide, "
- "or Click-Drag to pick several "
- "layers"),
- extend_mask & ~state,
- NULL, NULL, NULL);
+ case ALIGN_TOOL_REF_IDLE:
+ status = g_strdup (_("Click on a layer, path or guide, "
+ "or Click-Drag to pick a reference"));
break;
-
- case ALIGN_TOOL_PICK_LAYER:
- status = gimp_suggest_modifiers (_("Click to pick this layer as "
- "first item"),
- extend_mask & ~state,
+ case ALIGN_TOOL_REF_PICK_LAYER:
+ status = g_strdup (_("Click to pick this layer as reference"));
+ break;
+ case ALIGN_TOOL_REF_PICK_GUIDE:
+ status = gimp_suggest_modifiers (_("Click to pick this guide as reference"),
+ GDK_MOD1_MASK & ~state,
NULL, NULL, NULL);
break;
-
- case ALIGN_TOOL_ADD_LAYER:
- status = g_strdup (_("Click to add this layer to the list"));
+ case ALIGN_TOOL_REF_PICK_PATH:
+ status = g_strdup (_("Click to pick this path as reference"));
break;
- case ALIGN_TOOL_PICK_GUIDE:
- status = gimp_suggest_modifiers (_("Click to pick this guide as "
- "first item"),
- extend_mask & ~state,
- NULL, NULL, NULL);
+ case ALIGN_TOOL_REF_DRAG_BOX:
break;
- case ALIGN_TOOL_ADD_GUIDE:
- status = g_strdup (_("Click to add this guide to the list"));
+ case ALIGN_TOOL_ALIGN_IDLE:
+ status = g_strdup (_("Click on a guide to add it to objects to align, "
+ "click anywhere else to unselect all guides"));
break;
-
- case ALIGN_TOOL_PICK_PATH:
- status = gimp_suggest_modifiers (_("Click to pick this path as "
- "first item"),
+ case ALIGN_TOOL_ALIGN_PICK_GUIDE:
+ status = gimp_suggest_modifiers (_("Click to select this guide for alignment"),
extend_mask & ~state,
NULL, NULL, NULL);
break;
-
- case ALIGN_TOOL_ADD_PATH:
- status = g_strdup (_("Click to add this path to the list"));
+ case ALIGN_TOOL_ALIGN_ADD_GUIDE:
+ status = g_strdup (_("Click to add this guide to the list of objects to align"));
break;
- case ALIGN_TOOL_DRAG_BOX:
+ case ALIGN_TOOL_NO_ACTION:
break;
}
+ }
- if (status)
- {
- gimp_tool_push_status (tool, display, "%s", status);
- g_free (status);
- }
+ if (status)
+ {
+ gimp_tool_push_status (tool, display, "%s", status);
+ g_free (status);
}
}
static void
gimp_align_tool_draw (GimpDrawTool *draw_tool)
{
- GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (draw_tool);
- GList *list;
- gint x, y, w, h;
+ GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (draw_tool);
+ GimpAlignOptions *options = GIMP_ALIGN_TOOL_GET_OPTIONS (align_tool);
+ GObject *reference;
+ gint x, y, w, h;
/* draw rubber-band rectangle */
x = MIN (align_tool->x2, align_tool->x1);
@@ -603,86 +570,84 @@ gimp_align_tool_draw (GimpDrawTool *draw_tool)
w = MAX (align_tool->x2, align_tool->x1) - x;
h = MAX (align_tool->y2, align_tool->y1) - y;
- gimp_draw_tool_add_rectangle (draw_tool, FALSE, x, y, w, h);
+ if (w != 0 && h != 0)
+ gimp_draw_tool_add_rectangle (draw_tool, FALSE, x, y, w, h);
- for (list = align_tool->selected_objects;
- list;
- list = g_list_next (list))
+ /* Draw handles on the reference object. */
+ reference = gimp_align_options_get_reference (options, FALSE);
+ if (GIMP_IS_ITEM (reference))
{
- if (GIMP_IS_ITEM (list->data))
- {
- GimpItem *item = list->data;
- gint off_x, off_y;
-
- gimp_item_bounds (item, &x, &y, &w, &h);
-
- gimp_item_get_offset (item, &off_x, &off_y);
- x += off_x;
- y += off_y;
+ GimpItem *item = GIMP_ITEM (reference);
+ gint off_x, off_y;
+
+ gimp_item_bounds (item, &x, &y, &w, &h);
+
+ gimp_item_get_offset (item, &off_x, &off_y);
+ x += off_x;
+ y += off_y;
+
+ gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE,
+ x, y,
+ GIMP_TOOL_HANDLE_SIZE_SMALL,
+ GIMP_TOOL_HANDLE_SIZE_SMALL,
+ GIMP_HANDLE_ANCHOR_NORTH_WEST);
+ gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE,
+ x + w, y,
+ GIMP_TOOL_HANDLE_SIZE_SMALL,
+ GIMP_TOOL_HANDLE_SIZE_SMALL,
+ GIMP_HANDLE_ANCHOR_NORTH_EAST);
+ gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE,
+ x, y + h,
+ GIMP_TOOL_HANDLE_SIZE_SMALL,
+ GIMP_TOOL_HANDLE_SIZE_SMALL,
+ GIMP_HANDLE_ANCHOR_SOUTH_WEST);
+ gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE,
+ x + w, y + h,
+ GIMP_TOOL_HANDLE_SIZE_SMALL,
+ GIMP_TOOL_HANDLE_SIZE_SMALL,
+ GIMP_HANDLE_ANCHOR_SOUTH_EAST);
+ }
+ else if (GIMP_IS_GUIDE (reference))
+ {
+ GimpGuide *guide = GIMP_GUIDE (reference);
+ GimpImage *image = gimp_display_get_image (GIMP_TOOL (draw_tool)->display);
+ gint x, y;
+ gint w, h;
+ switch (gimp_guide_get_orientation (guide))
+ {
+ case GIMP_ORIENTATION_VERTICAL:
+ x = gimp_guide_get_position (guide);
+ h = gimp_image_get_height (image);
gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE,
- x, y,
+ x, h,
GIMP_TOOL_HANDLE_SIZE_SMALL,
GIMP_TOOL_HANDLE_SIZE_SMALL,
- GIMP_HANDLE_ANCHOR_NORTH_WEST);
+ GIMP_HANDLE_ANCHOR_SOUTH);
gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE,
- x + w, y,
+ x, 0,
GIMP_TOOL_HANDLE_SIZE_SMALL,
GIMP_TOOL_HANDLE_SIZE_SMALL,
- GIMP_HANDLE_ANCHOR_NORTH_EAST);
+ GIMP_HANDLE_ANCHOR_NORTH);
+ break;
+
+ case GIMP_ORIENTATION_HORIZONTAL:
+ y = gimp_guide_get_position (guide);
+ w = gimp_image_get_width (image);
gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE,
- x, y + h,
+ w, y,
GIMP_TOOL_HANDLE_SIZE_SMALL,
GIMP_TOOL_HANDLE_SIZE_SMALL,
- GIMP_HANDLE_ANCHOR_SOUTH_WEST);
+ GIMP_HANDLE_ANCHOR_EAST);
gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE,
- x + w, y + h,
+ 0, y,
GIMP_TOOL_HANDLE_SIZE_SMALL,
GIMP_TOOL_HANDLE_SIZE_SMALL,
- GIMP_HANDLE_ANCHOR_SOUTH_EAST);
- }
- else if (GIMP_IS_GUIDE (list->data))
- {
- GimpGuide *guide = list->data;
- GimpImage *image = gimp_display_get_image (GIMP_TOOL (draw_tool)->display);
- gint x, y;
- gint w, h;
-
- switch (gimp_guide_get_orientation (guide))
- {
- case GIMP_ORIENTATION_VERTICAL:
- x = gimp_guide_get_position (guide);
- h = gimp_image_get_height (image);
- gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE,
- x, h,
- GIMP_TOOL_HANDLE_SIZE_SMALL,
- GIMP_TOOL_HANDLE_SIZE_SMALL,
- GIMP_HANDLE_ANCHOR_SOUTH);
- gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE,
- x, 0,
- GIMP_TOOL_HANDLE_SIZE_SMALL,
- GIMP_TOOL_HANDLE_SIZE_SMALL,
- GIMP_HANDLE_ANCHOR_NORTH);
- break;
-
- case GIMP_ORIENTATION_HORIZONTAL:
- y = gimp_guide_get_position (guide);
- w = gimp_image_get_width (image);
- gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE,
- w, y,
- GIMP_TOOL_HANDLE_SIZE_SMALL,
- GIMP_TOOL_HANDLE_SIZE_SMALL,
- GIMP_HANDLE_ANCHOR_EAST);
- gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE,
- 0, y,
- GIMP_TOOL_HANDLE_SIZE_SMALL,
- GIMP_TOOL_HANDLE_SIZE_SMALL,
- GIMP_HANDLE_ANCHOR_WEST);
- break;
+ GIMP_HANDLE_ANCHOR_WEST);
+ break;
- default:
- break;
- }
+ default:
+ break;
}
}
}
@@ -694,14 +659,16 @@ gimp_align_tool_align (GimpAlignTool *align_tool,
GimpAlignOptions *options = GIMP_ALIGN_TOOL_GET_OPTIONS (align_tool);
GimpImage *image;
GObject *reference_object = NULL;
+ GList *objects;
GList *list;
gint offset = 0;
/* if nothing is selected, just return */
- if (! align_tool->selected_objects)
+ objects = gimp_align_options_get_objects (options);
+ if (! objects)
return;
- image = gimp_display_get_image (GIMP_TOOL (align_tool)->display);
+ image = gimp_context_get_image (gimp_get_user_context (GIMP_CONTEXT (options)->gimp));
switch (align_type)
{
@@ -734,50 +701,9 @@ gimp_align_tool_align (GimpAlignTool *align_tool,
* "set_reference" is TRUE, otherwise use NULL.
*/
- list = align_tool->selected_objects;
-
- switch (options->align_reference)
- {
- case GIMP_ALIGN_REFERENCE_IMAGE:
- reference_object = G_OBJECT (image);
- break;
-
- case GIMP_ALIGN_REFERENCE_FIRST:
- if (g_list_length (list) == 1)
- {
- reference_object = G_OBJECT (image);
- }
- else
- {
- if (align_tool->set_reference)
- {
- reference_object = G_OBJECT (list->data);
- list = g_list_next (list);
- }
- else
- {
- reference_object = NULL;
- }
- }
- break;
-
- case GIMP_ALIGN_REFERENCE_SELECTION:
- reference_object = G_OBJECT (gimp_image_get_mask (image));
- break;
-
- case GIMP_ALIGN_REFERENCE_ACTIVE_LAYER:
- reference_object = G_OBJECT (gimp_image_get_active_layer (image));
- break;
-
- case GIMP_ALIGN_REFERENCE_ACTIVE_CHANNEL:
- reference_object = G_OBJECT (gimp_image_get_active_channel (image));
- break;
-
- case GIMP_ALIGN_REFERENCE_ACTIVE_PATH:
- reference_object = G_OBJECT (gimp_image_get_active_vectors (image));
- break;
- }
+ list = objects;
+ reference_object = gimp_align_options_get_reference (options, TRUE);
if (! reference_object)
return;
@@ -792,33 +718,5 @@ gimp_align_tool_align (GimpAlignTool *align_tool,
gimp_draw_tool_resume (GIMP_DRAW_TOOL (align_tool));
gimp_image_flush (image);
-}
-
-static void
-gimp_align_tool_object_removed (GObject *object,
- GimpAlignTool *align_tool)
-{
- gimp_draw_tool_pause (GIMP_DRAW_TOOL (align_tool));
-
- if (align_tool->selected_objects)
- g_signal_handlers_disconnect_by_func (object,
- gimp_align_tool_object_removed,
- align_tool);
-
- align_tool->selected_objects = g_list_remove (align_tool->selected_objects,
- object);
-
- gimp_draw_tool_resume (GIMP_DRAW_TOOL (align_tool));
-}
-
-static void
-gimp_align_tool_clear_selected (GimpAlignTool *align_tool)
-{
- gimp_draw_tool_pause (GIMP_DRAW_TOOL (align_tool));
-
- while (align_tool->selected_objects)
- gimp_align_tool_object_removed (align_tool->selected_objects->data,
- align_tool);
-
- gimp_draw_tool_resume (GIMP_DRAW_TOOL (align_tool));
+ g_list_free (objects);
}
diff --git a/app/tools/gimpaligntool.h b/app/tools/gimpaligntool.h
index e84a9cbdf8..2bf666f2e9 100644
--- a/app/tools/gimpaligntool.h
+++ b/app/tools/gimpaligntool.h
@@ -25,14 +25,17 @@
/* tool function/operation/state/mode */
typedef enum
{
- ALIGN_TOOL_IDLE,
- ALIGN_TOOL_PICK_LAYER,
- ALIGN_TOOL_ADD_LAYER,
- ALIGN_TOOL_PICK_GUIDE,
- ALIGN_TOOL_ADD_GUIDE,
- ALIGN_TOOL_PICK_PATH,
- ALIGN_TOOL_ADD_PATH,
- ALIGN_TOOL_DRAG_BOX
+ ALIGN_TOOL_NO_ACTION,
+
+ ALIGN_TOOL_REF_IDLE,
+ ALIGN_TOOL_REF_PICK_LAYER,
+ ALIGN_TOOL_REF_PICK_GUIDE,
+ ALIGN_TOOL_REF_PICK_PATH,
+ ALIGN_TOOL_REF_DRAG_BOX,
+
+ ALIGN_TOOL_ALIGN_IDLE,
+ ALIGN_TOOL_ALIGN_PICK_GUIDE,
+ ALIGN_TOOL_ALIGN_ADD_GUIDE,
} GimpAlignToolFunction;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]