/* GIMP - The GNU 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 3 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, see . */ #include "config.h" #include #include #include "libgimpbase/gimpbase.h" #include "libgimpconfig/gimpconfig.h" #include "libgimpwidgets/gimpwidgets.h" #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/gimppath.h" #include "widgets/gimppivotselector.h" #include "widgets/gimppropwidgets.h" #include "widgets/gimpwidgets-utils.h" #include "gimpalignoptions.h" #include "gimptooloptions-gui.h" #include "gimp-intl.h" #define ALIGN_VER_N_BUTTONS 3 #define ALIGN_HOR_N_BUTTONS 3 #define DISTR_VER_N_BUTTONS 2 #define DISTR_HOR_N_BUTTONS 2 enum { ALIGN_BUTTON_CLICKED, LAST_SIGNAL }; enum { PROP_0, PROP_ALIGN_REFERENCE, PROP_ALIGN_LAYERS, PROP_ALIGN_VECTORS, PROP_ALIGN_CONTENTS, PROP_PIVOT_X, PROP_PIVOT_Y, }; struct _GimpAlignOptionsPrivate { GimpImage *image; gboolean align_layers; gboolean align_paths; gboolean align_contents; gdouble pivot_x; gdouble pivot_y; GList *selected_guides; GObject *reference; GtkWidget *selected_guides_label; GtkWidget *reference_combo; GtkWidget *reference_box; GtkWidget *reference_label; GtkWidget *pivot_selector; GtkWidget *align_ver_button[ALIGN_VER_N_BUTTONS]; GtkWidget *align_hor_button[ALIGN_HOR_N_BUTTONS]; GtkWidget *distr_ver_button[DISTR_VER_N_BUTTONS]; GtkWidget *distr_hor_button[DISTR_HOR_N_BUTTONS]; }; 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); 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); static void gimp_align_options_pivot_changed (GimpPivotSelector *selector, GimpAlignOptions *options); G_DEFINE_TYPE_WITH_PRIVATE (GimpAlignOptions, gimp_align_options, GIMP_TYPE_TOOL_OPTIONS) #define parent_class gimp_align_options_parent_class static guint align_options_signals[LAST_SIGNAL] = { 0 }; static void 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; klass->align_button_clicked = NULL; align_options_signals[ALIGN_BUTTON_CLICKED] = g_signal_new ("align-button-clicked", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GimpAlignOptionsClass, align_button_clicked), NULL, NULL, NULL, G_TYPE_NONE, 1, GIMP_TYPE_ALIGNMENT_TYPE); GIMP_CONFIG_PROP_ENUM (object_class, PROP_ALIGN_REFERENCE, "align-reference", _("Relative to"), _("Reference object targets will be aligned on"), GIMP_TYPE_ALIGN_REFERENCE_TYPE, GIMP_ALIGN_REFERENCE_IMAGE, GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ALIGN_LAYERS, "align-layers", _("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", _("Selected paths"), _("Selected paths will be aligned or distributed by the tool"), FALSE, GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ALIGN_CONTENTS, "align-contents", _("Use extents of layer contents"), _("Instead of aligning or distributing on layer borders, use its content bounding box"), TRUE, GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_PIVOT_X, "pivot-x", "X position of the point to align in objects", NULL, 0.0, 1.0, 0.5, GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_PIVOT_Y, "pivot-y", "Y position of the point to align in objects", NULL, 0.0, 1.0, 0.5, 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); G_OBJECT_CLASS (parent_class)->finalize (object); } 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_REFERENCE: options->align_reference = g_value_get_enum (value); gimp_align_options_update_area (options); 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_paths = g_value_get_boolean (value); gimp_align_options_update_area (options); break; case PROP_ALIGN_CONTENTS: options->priv->align_contents = g_value_get_boolean (value); break; case PROP_PIVOT_X: options->priv->pivot_x = g_value_get_double (value); break; case PROP_PIVOT_Y: options->priv->pivot_y = g_value_get_double (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_REFERENCE: g_value_set_enum (value, options->align_reference); 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_paths); break; case PROP_ALIGN_CONTENTS: g_value_set_boolean (value, options->priv->align_contents); break; case PROP_PIVOT_X: g_value_set_double (value, options->priv->pivot_x); break; case PROP_PIVOT_Y: g_value_set_double (value, options->priv->pivot_y); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gimp_align_options_button_clicked (GtkButton *button, GimpAlignOptions *options) { GimpAlignmentType action; action = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "align-action")); g_signal_emit (options, align_options_signals[ALIGN_BUTTON_CLICKED], 0, action); } static GtkWidget * gimp_align_options_button_new (GimpAlignOptions *options, GimpAlignmentType action, GtkWidget *parent, const gchar *tooltip) { GtkWidget *button; GtkWidget *image; const gchar *icon_name = NULL; switch (action) { case GIMP_ALIGN_LEFT: icon_name = GIMP_ICON_GRAVITY_WEST; break; case GIMP_ALIGN_HCENTER: icon_name = GIMP_ICON_CENTER_HORIZONTAL; break; case GIMP_ALIGN_RIGHT: icon_name = GIMP_ICON_GRAVITY_EAST; break; case GIMP_ALIGN_TOP: icon_name = GIMP_ICON_GRAVITY_NORTH; break; case GIMP_ALIGN_VCENTER: icon_name = GIMP_ICON_CENTER_VERTICAL; break; case GIMP_ALIGN_BOTTOM: icon_name = GIMP_ICON_GRAVITY_SOUTH; break; case GIMP_ARRANGE_HFILL: icon_name = GIMP_ICON_FILL_HORIZONTAL; break; case GIMP_ARRANGE_VFILL: icon_name = GIMP_ICON_FILL_VERTICAL; break; case GIMP_DISTRIBUTE_EVEN_HORIZONTAL_GAP: icon_name = GIMP_ICON_EVEN_HORIZONTAL_GAP; break; case GIMP_DISTRIBUTE_EVEN_VERTICAL_GAP: icon_name = GIMP_ICON_EVEN_VERTICAL_GAP; break; default: g_return_val_if_reached (NULL); break; } button = gtk_button_new (); gtk_widget_set_sensitive (button, FALSE); gtk_widget_show (button); image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON); gtk_container_add (GTK_CONTAINER (button), image); gtk_widget_show (image); gtk_box_pack_start (GTK_BOX (parent), button, FALSE, FALSE, 0); gtk_widget_show (button); gimp_help_set_help_data (button, tooltip, NULL); g_object_set_data (G_OBJECT (button), "align-action", GINT_TO_POINTER (action)); g_signal_connect (button, "clicked", G_CALLBACK (gimp_align_options_button_clicked), options); return button; } GtkWidget * 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 *section_vbox; GtkWidget *items_grid; GtkWidget *hbox; GtkWidget *frame; GtkWidget *combo; gchar *text; gint n = 0; /* Selected objects */ frame = gimp_frame_new (_("Targets")); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); section_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); gtk_container_add (GTK_CONTAINER (frame), section_vbox); gtk_widget_show (section_vbox); items_grid = gtk_grid_new (); gtk_container_add (GTK_CONTAINER (section_vbox), items_grid); gtk_widget_show (items_grid); widget = gimp_prop_check_button_new (config, "align-contents", NULL); widget = gimp_prop_expanding_frame_new (config, "align-layers", NULL, widget, NULL); gtk_grid_attach (GTK_GRID (items_grid), widget, 0, 0, 1, 1); widget = gimp_prop_check_button_new (config, "align-vectors", NULL); gtk_grid_attach (GTK_GRID (items_grid), widget, 0, 1, 1, 1); options->priv->pivot_selector = gimp_pivot_selector_new (0.0, 0.0, 1.0, 1.0); gtk_widget_set_tooltip_text (options->priv->pivot_selector, _("Set anchor point of targets")); gimp_pivot_selector_set_position (GIMP_PIVOT_SELECTOR (options->priv->pivot_selector), options->priv->pivot_x, options->priv->pivot_y); gtk_grid_attach (GTK_GRID (items_grid), options->priv->pivot_selector, 1, 0, 1, 2); gtk_widget_show (options->priv->pivot_selector); g_signal_connect (options->priv->pivot_selector, "changed", G_CALLBACK (gimp_align_options_pivot_changed), options); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start (GTK_BOX (section_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 target guides (%s-%s to add 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 (section_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); section_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); gtk_container_add (GTK_CONTAINER (frame), section_vbox); gtk_widget_show (section_vbox); /* Align frame: reference */ combo = gimp_prop_enum_combo_box_new (config, "align-reference", 0, 0); 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 (section_vbox), combo, FALSE, FALSE, 0); options->priv->reference_combo = combo; hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start (GTK_BOX (section_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); widget = gtk_label_new (NULL); gtk_box_pack_start (GTK_BOX (section_vbox), widget, FALSE, FALSE, 0); gtk_widget_show (widget); options->priv->reference_label = widget; /* Align frame: buttons */ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start (GTK_BOX (section_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); n = 0; options->priv->align_ver_button[n++] = gimp_align_options_button_new (options, GIMP_ALIGN_LEFT, hbox, _("Align anchor points of targets on left edge of reference")); options->priv->align_ver_button[n++] = gimp_align_options_button_new (options, GIMP_ALIGN_HCENTER, hbox, _("Align anchor points of targets on vertical middle of reference")); options->priv->align_ver_button[n++] = gimp_align_options_button_new (options, GIMP_ALIGN_RIGHT, hbox, _("Align anchor points of targets on right edge of reference")); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start (GTK_BOX (section_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); n = 0; options->priv->align_hor_button[n++] = gimp_align_options_button_new (options, GIMP_ALIGN_TOP, hbox, _("Align anchor points of targets on top edge of reference")); options->priv->align_hor_button[n++] = gimp_align_options_button_new (options, GIMP_ALIGN_VCENTER, hbox, _("Align anchor points of targets on horizontal middle of reference")); options->priv->align_hor_button[n++] = gimp_align_options_button_new (options, GIMP_ALIGN_BOTTOM, hbox, _("Align anchor points of targets on bottom of reference")); /* Distribute frame */ frame = gimp_frame_new (_("Distribute")); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); section_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); gtk_container_add (GTK_CONTAINER (frame), section_vbox); gtk_widget_show (section_vbox); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start (GTK_BOX (section_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); n = 0; options->priv->distr_ver_button[n++] = gimp_align_options_button_new (options, GIMP_ARRANGE_HFILL, hbox, _("Distribute anchor points of targets evenly in the horizontal")); options->priv->distr_ver_button[n++] = gimp_align_options_button_new (options, GIMP_DISTRIBUTE_EVEN_HORIZONTAL_GAP, hbox, _("Distribute horizontally with even horizontal gaps")); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start (GTK_BOX (section_vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); n = 0; options->priv->distr_hor_button[n++] = gimp_align_options_button_new (options, GIMP_ARRANGE_VFILL, hbox, _("Distribute anchor points of targets evenly in the vertical")); options->priv->distr_hor_button[n++] = gimp_align_options_button_new (options, GIMP_DISTRIBUTE_EVEN_VERTICAL_GAP, hbox, _("Distribute vertically with even vertical gaps")); g_signal_connect_object (gimp_get_user_context (GIMP_CONTEXT (options)->gimp), "image-changed", G_CALLBACK (gimp_align_options_image_changed), tool_options, 0); 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_paths) { GList *vectors; vectors = gimp_image_get_selected_paths (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_get_pivot (GimpAlignOptions *options, gdouble *x, gdouble *y) { gimp_pivot_selector_get_position (GIMP_PIVOT_SELECTOR (options->priv->pivot_selector), x, y); } 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; } gboolean gimp_align_options_align_contents (GimpAlignOptions *options) { return options->priv->align_contents; } 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) { if (image != options->priv->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 (options->priv->image) { g_signal_handlers_disconnect_by_func (options->priv->image, G_CALLBACK (gimp_align_options_update_area), options); g_signal_handlers_disconnect_by_func (options->priv->image, G_CALLBACK (gimp_align_options_guide_removed), options); } g_set_weak_pointer (&options->priv->image, image); 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); } gimp_align_options_update_area (options); } } static void gimp_align_options_update_area (GimpAlignOptions *options) { GimpImage *image; GList *layers = NULL; GList *paths = NULL; gboolean enable_ver_align = FALSE; gboolean enable_hor_align = FALSE; gboolean enable_ver_distr = FALSE; gboolean enable_hor_distr = FALSE; 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); paths = gimp_image_get_selected_paths (image); if (options->priv->align_layers) n_items += g_list_length (layers); if (options->priv->align_paths) n_items += g_list_length (paths); n_items += g_list_length (options->priv->selected_guides); } if (n_items > 0) { GObject *reference; reference = gimp_align_options_get_reference (options, FALSE); enable_ver_align = (reference != NULL && (! GIMP_IS_GUIDE (reference) || gimp_guide_get_orientation (GIMP_GUIDE (reference)) == GIMP_ORIENTATION_VERTICAL)); enable_hor_align = (reference != NULL && (! GIMP_IS_GUIDE (reference) || gimp_guide_get_orientation (GIMP_GUIDE (reference)) == GIMP_ORIENTATION_HORIZONTAL)); enable_ver_distr = enable_hor_distr = (n_items > 2); } for (gint i = 0; i < ALIGN_VER_N_BUTTONS; i++) gtk_widget_set_sensitive (options->priv->align_ver_button[i], enable_ver_align); for (gint i = 0; i < ALIGN_HOR_N_BUTTONS; i++) gtk_widget_set_sensitive (options->priv->align_hor_button[i], enable_hor_align); for (gint i = 0; i < DISTR_VER_N_BUTTONS; i++) gtk_widget_set_sensitive (options->priv->distr_ver_button[i], enable_ver_distr); for (gint i = 0; i < DISTR_HOR_N_BUTTONS; i++) gtk_widget_set_sensitive (options->priv->distr_hor_button[i], enable_hor_distr); /* 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 ("%s", 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_PATH (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 ("%s", 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); } static void gimp_align_options_pivot_changed (GimpPivotSelector *selector, GimpAlignOptions *options) { gdouble x; gdouble y; gimp_pivot_selector_get_position (selector, &x, &y); g_object_set (options, "pivot-x", x, "pivot-y", y, NULL); }