Files
gimp/app/gui/layers-commands.c
Michael Natterer 1329e016d2 app/core/gimpimage-mask.[ch] (gimp_image_mask_translate) added "gboolean
2003-03-18  Michael Natterer  <mitch@gimp.org>

	* app/core/gimpimage-mask.[ch] (gimp_image_mask_translate)
	* app/core/gimplayer.[ch] (gimp_layer_translate): added
	"gboolean push_undo" parameters.

	* app/core/gimpimage-crop.c
	* app/core/gimpimage-resize.c
	* app/display/gimpdisplayshell-dnd.c
	* app/gui/layers-commands.c
	* app/widgets/gimptoolbox.c
	* tools/pdbgen/pdb/layer.pdb
	* tools/pdbgen/pdb/selection.pdb: changed accordingly.

	* app/pdb/layer_cmds.c
	* app/pdb/selection_cmds.c: regenerated.

	* app/core/gimpimage-undo-push.c (undo_pop_layer_displace): call
	gimp_layer_translate() with "push_undo == FALSE" instead of
	duplicating gimp_layer_translate()'s code. Use GimpItemUndo for
	GIMP_UNDO_MASK.

	* app/tools/gimpeditselectiontool.c
	(gimp_edit_selection_tool_cursor_key): check if the top undo on
	the stack is of exactly the same type as the undo we would push
	and just don't push it then (compresses layer translate undos and
	fixes bug #86362). Changed stuff work with CAPS_LOCK or other
	modifiers pressed.
2003-03-18 16:42:45 +00:00

1100 lines
30 KiB
C

/* 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 <string.h>
#include <gtk/gtk.h>
#include "libgimpmath/gimpmath.h"
#include "libgimpbase/gimpbase.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "gui-types.h"
#include "core/gimp.h"
#include "core/gimpcontext.h"
#include "core/gimpimage.h"
#include "core/gimpimage-mask.h"
#include "core/gimpimage-merge.h"
#include "core/gimpimage-undo.h"
#include "core/gimplayer.h"
#include "core/gimplayer-floating-sel.h"
#include "core/gimplayermask.h"
#include "core/gimplist.h"
#include "pdb/procedural_db.h"
#include "widgets/gimpenummenu.h"
#include "widgets/gimpitemlistview.h"
#include "widgets/gimpitemtreeview.h"
#include "widgets/gimpviewabledialog.h"
#include "display/gimpdisplay.h"
#include "layers-commands.h"
#include "resize-dialog.h"
#include "libgimp/gimpintl.h"
/* local function prototypes */
static void layers_add_mask_query (GimpLayer *layer);
static void layers_scale_layer_query (GimpImage *gimage,
GimpLayer *layer);
static void layers_resize_layer_query (GimpImage *gimage,
GimpLayer *layer);
#define return_if_no_image(gimage,data) \
if (GIMP_IS_DISPLAY (data)) \
gimage = ((GimpDisplay *) data)->gimage; \
else if (GIMP_IS_GIMP (data)) \
gimage = gimp_context_get_image (gimp_get_user_context (GIMP (data))); \
else if (GIMP_IS_ITEM_LIST_VIEW (data)) \
gimage = ((GimpItemListView *) data)->gimage; \
else if (GIMP_IS_ITEM_TREE_VIEW (data)) \
gimage = ((GimpItemTreeView *) data)->gimage; \
else \
gimage = NULL; \
\
if (! gimage) \
return
#define return_if_no_layer(gimage,layer,data) \
return_if_no_image (gimage,data); \
layer = gimp_image_get_active_layer (gimage); \
if (! layer) \
return
/* public functions */
void
layers_previous_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *new_layer;
gint current_layer;
return_if_no_image (gimage, data);
current_layer =
gimp_image_get_layer_index (gimage, gimp_image_get_active_layer (gimage));
if (current_layer > 0)
{
new_layer = (GimpLayer *)
gimp_container_get_child_by_index (gimage->layers, current_layer - 1);
if (new_layer)
{
gimp_image_set_active_layer (gimage, new_layer);
gimp_image_flush (gimage);
}
}
}
void
layers_next_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *new_layer;
gint current_layer;
return_if_no_image (gimage, data);
current_layer =
gimp_image_get_layer_index (gimage, gimp_image_get_active_layer (gimage));
new_layer =
GIMP_LAYER (gimp_container_get_child_by_index (gimage->layers,
current_layer + 1));
if (new_layer)
{
gimp_image_set_active_layer (gimage, new_layer);
gimp_image_flush (gimage);
}
}
void
layers_raise_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
gimp_image_raise_layer (gimage, active_layer);
gimp_image_flush (gimage);
}
void
layers_lower_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
gimp_image_lower_layer (gimage, active_layer);
gimp_image_flush (gimage);
}
void
layers_raise_to_top_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
gimp_image_raise_layer_to_top (gimage, active_layer);
gimp_image_flush (gimage);
}
void
layers_lower_to_bottom_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
gimp_image_lower_layer_to_bottom (gimage, active_layer);
gimp_image_flush (gimage);
}
void
layers_new_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
return_if_no_image (gimage, data);
layers_new_layer_query (gimage, NULL, TRUE);
}
void
layers_duplicate_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
GimpLayer *new_layer;
return_if_no_layer (gimage, active_layer, data);
new_layer =
GIMP_LAYER (gimp_item_duplicate (GIMP_ITEM (active_layer),
G_TYPE_FROM_INSTANCE (active_layer),
TRUE));
gimp_image_add_layer (gimage, new_layer, -1);
gimp_image_flush (gimage);
}
void
layers_anchor_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
if (gimp_layer_is_floating_sel (active_layer))
{
floating_sel_anchor (active_layer);
gimp_image_flush (gimage);
}
}
void
layers_merge_down_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
gimp_image_merge_down (gimage, active_layer, GIMP_EXPAND_AS_NECESSARY);
gimp_image_flush (gimage);
}
void
layers_delete_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
if (gimp_layer_is_floating_sel (active_layer))
floating_sel_remove (active_layer);
else
gimp_image_remove_layer (gimage, active_layer);
gimp_image_flush (gimage);
}
void
layers_resize_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
layers_resize_layer_query (gimage, active_layer);
}
void
layers_resize_to_image_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
gimp_layer_resize_to_image (active_layer);
gimp_image_flush (gimage);
}
void
layers_scale_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
layers_scale_layer_query (gimage, active_layer);
}
void
layers_crop_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
gint x1, y1, x2, y2;
gint off_x, off_y;
return_if_no_layer (gimage, active_layer, data);
if (! gimp_image_mask_bounds (gimage, &x1, &y1, &x2, &y2))
{
g_message (_("Cannot crop because the current selection is empty."));
return;
}
gimp_drawable_offsets (GIMP_DRAWABLE (active_layer), &off_x, &off_y);
off_x -= x1;
off_y -= y1;
gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_LAYER_RESIZE,
_("Crop Layer"));
if (gimp_layer_is_floating_sel (active_layer))
floating_sel_relax (active_layer, TRUE);
gimp_layer_resize (active_layer, x2 - x1, y2 - y1, off_x, off_y);
if (gimp_layer_is_floating_sel (active_layer))
floating_sel_rigor (active_layer, TRUE);
gimp_image_undo_group_end (gimage);
gimp_image_flush (gimage);
}
void
layers_add_layer_mask_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
layers_add_mask_query (active_layer);
}
void
layers_apply_layer_mask_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
if (gimp_layer_get_mask (active_layer))
{
gboolean flush;
flush = ! active_layer->mask->apply_mask || active_layer->mask->show_mask;
gimp_layer_apply_mask (active_layer, GIMP_MASK_APPLY, TRUE);
if (flush)
gimp_image_flush (gimage);
}
}
void
layers_delete_layer_mask_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
if (gimp_layer_get_mask (active_layer))
{
gboolean flush;
flush = active_layer->mask->apply_mask || active_layer->mask->show_mask;
gimp_layer_apply_mask (active_layer, GIMP_MASK_DISCARD, TRUE);
if (flush)
gimp_image_flush (gimage);
}
}
void
layers_mask_select_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
if (gimp_layer_get_mask (active_layer))
{
gimp_image_mask_layer_mask (gimage, active_layer);
gimp_image_flush (gimage);
}
}
void
layers_alpha_select_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
gimp_image_mask_layer_alpha (gimage, active_layer);
gimp_image_flush (gimage);
}
void
layers_add_alpha_channel_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
if (! gimp_drawable_has_alpha (GIMP_DRAWABLE (active_layer)))
{
gimp_layer_add_alpha (active_layer);
gimp_image_flush (gimage);
}
}
void
layers_edit_attributes_cmd_callback (GtkWidget *widget,
gpointer data)
{
GimpImage *gimage;
GimpLayer *active_layer;
return_if_no_layer (gimage, active_layer, data);
layers_edit_layer_query (active_layer);
}
/********************************/
/* The new layer query dialog */
/********************************/
typedef struct _NewLayerOptions NewLayerOptions;
struct _NewLayerOptions
{
GtkWidget *query_box;
GtkWidget *name_entry;
GtkWidget *size_se;
GimpFillType fill_type;
gint xsize;
gint ysize;
GimpImage *gimage;
};
static GimpFillType fill_type = GIMP_TRANSPARENT_FILL;
static gchar *layer_name = NULL;
static void
new_layer_query_ok_callback (GtkWidget *widget,
gpointer data)
{
NewLayerOptions *options;
GimpLayer *layer;
GimpImage *gimage;
options = (NewLayerOptions *) data;
if (layer_name)
g_free (layer_name);
layer_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (options->name_entry)));
options->xsize =
RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (options->size_se), 0));
options->ysize =
RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (options->size_se), 1));
fill_type = options->fill_type;
if ((gimage = options->gimage))
{
layer = gimp_layer_new (gimage,
options->xsize,
options->ysize,
gimp_image_base_type_with_alpha (gimage),
layer_name,
GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE);
if (layer)
{
gimp_drawable_fill_by_type (GIMP_DRAWABLE (layer),
gimp_get_user_context (gimage->gimp),
fill_type);
gimp_image_add_layer (gimage, layer, -1);
gimp_image_flush (gimage);
}
else
{
g_message ("new_layer_query_ok_callback():\n"
"could not allocate new layer");
}
}
gtk_widget_destroy (options->query_box);
}
void
layers_new_layer_query (GimpImage *gimage,
GimpLayer *template,
gboolean interactive)
{
NewLayerOptions *options;
GimpLayer *floating_sel;
GtkWidget *vbox;
GtkWidget *table;
GtkWidget *label;
GtkObject *adjustment;
GtkWidget *spinbutton;
GtkWidget *frame;
GtkWidget *button;
g_return_if_fail (GIMP_IS_IMAGE (gimage));
g_return_if_fail (! template || GIMP_IS_LAYER (template));
/* If there is a floating selection, the new command transforms
* the current fs into a new layer
*/
if ((floating_sel = gimp_image_floating_sel (gimage)))
{
floating_sel_to_layer (floating_sel);
gimp_image_flush (gimage);
return;
}
if (template || ! interactive)
{
GimpLayer *new_layer;
gint width, height;
gint off_x, off_y;
gdouble opacity;
GimpLayerModeEffects mode;
if (template)
{
width = gimp_drawable_width (GIMP_DRAWABLE (template));
height = gimp_drawable_height (GIMP_DRAWABLE (template));
gimp_drawable_offsets (GIMP_DRAWABLE (template), &off_x, &off_y);
opacity = template->opacity;
mode = template->mode;
}
else
{
width = gimp_image_get_width (gimage);
height = gimp_image_get_height (gimage);
off_x = 0;
off_y = 0;
opacity = 1.0;
mode = GIMP_NORMAL_MODE;
}
gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_EDIT_PASTE,
_("New Layer"));
new_layer = gimp_layer_new (gimage,
width,
height,
gimp_image_base_type_with_alpha (gimage),
_("Empty Layer Copy"),
opacity,
mode);
if (template)
{
gimp_drawable_fill_by_type (GIMP_DRAWABLE (new_layer),
gimp_get_user_context (gimage->gimp),
GIMP_TRANSPARENT_FILL);
gimp_layer_translate (new_layer, off_x, off_y, FALSE);
}
gimp_image_add_layer (gimage, new_layer, -1);
gimp_image_undo_group_end (gimage);
return;
}
options = g_new0 (NewLayerOptions, 1);
options->fill_type = fill_type;
options->gimage = gimage;
/* The dialog */
options->query_box =
gimp_viewable_dialog_new (GIMP_VIEWABLE (gimage),
_("New Layer"), "new_layer_options",
GTK_STOCK_NEW,
_("Create a New Layer"),
gimp_standard_help_func,
"dialogs/layers/new_layer.html",
GTK_STOCK_CANCEL, gtk_widget_destroy,
NULL, 1, NULL, FALSE, TRUE,
GTK_STOCK_OK, new_layer_query_ok_callback,
options, NULL, NULL, TRUE, FALSE,
NULL);
g_object_weak_ref (G_OBJECT (options->query_box),
(GWeakNotify) g_free,
options);
/* The main vbox */
vbox = gtk_vbox_new (FALSE, 4);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (options->query_box)->vbox),
vbox);
table = gtk_table_new (3, 2, FALSE);
gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4);
gtk_table_set_row_spacing (GTK_TABLE (table), 0, 4);
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
/* The name label and entry */
options->name_entry = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY (options->name_entry),
(layer_name ? layer_name : _("New Layer")));
gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
_("Layer _Name:"), 1.0, 0.5,
options->name_entry, 1, FALSE);
/* The size labels */
label = gtk_label_new (_("Layer Width:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
gtk_widget_show (label);
label = gtk_label_new (_("Height:"));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
gtk_widget_show (label);
/* The size sizeentry */
spinbutton = gimp_spin_button_new (&adjustment,
1, 1, 1, 1, 10, 1,
1, 2);
gtk_entry_set_width_chars (GTK_ENTRY (spinbutton), 10);
options->size_se = gimp_size_entry_new (1, gimage->unit, "%a",
TRUE, TRUE, FALSE, 10,
GIMP_SIZE_ENTRY_UPDATE_SIZE);
gtk_table_set_col_spacing (GTK_TABLE (options->size_se), 1, 4);
gtk_table_set_row_spacing (GTK_TABLE (options->size_se), 0, 2);
gimp_size_entry_add_field (GIMP_SIZE_ENTRY (options->size_se),
GTK_SPIN_BUTTON (spinbutton), NULL);
gtk_table_attach_defaults (GTK_TABLE (options->size_se), spinbutton,
1, 2, 0, 1);
gtk_widget_show (spinbutton);
gtk_table_attach (GTK_TABLE (table), options->size_se, 1, 2, 1, 3,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (options->size_se);
gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (options->size_se),
GIMP_UNIT_PIXEL);
gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (options->size_se), 0,
gimage->xresolution, FALSE);
gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (options->size_se), 1,
gimage->yresolution, FALSE);
gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (options->size_se), 0,
GIMP_MIN_IMAGE_SIZE,
GIMP_MAX_IMAGE_SIZE);
gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (options->size_se), 1,
GIMP_MIN_IMAGE_SIZE,
GIMP_MAX_IMAGE_SIZE);
gimp_size_entry_set_size (GIMP_SIZE_ENTRY (options->size_se), 0,
0, gimage->width);
gimp_size_entry_set_size (GIMP_SIZE_ENTRY (options->size_se), 1,
0, gimage->height);
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (options->size_se), 0,
gimage->width);
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (options->size_se), 1,
gimage->height);
gtk_widget_show (table);
/* The radio frame */
frame = gimp_enum_radio_frame_new_with_range (GIMP_TYPE_FILL_TYPE,
GIMP_FOREGROUND_FILL,
GIMP_TRANSPARENT_FILL,
gtk_label_new (_("Layer Fill Type")),
2,
G_CALLBACK (gimp_radio_button_update),
&options->fill_type,
&button);
gimp_radio_group_set_active (GTK_RADIO_BUTTON (button),
GINT_TO_POINTER (options->fill_type));
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
gtk_widget_show (vbox);
gtk_widget_show (options->query_box);
}
/**************************************/
/* The edit layer attributes dialog */
/**************************************/
typedef struct _EditLayerOptions EditLayerOptions;
struct _EditLayerOptions
{
GtkWidget *query_box;
GtkWidget *name_entry;
GimpLayer *layer;
GimpImage *gimage;
};
static void
edit_layer_query_ok_callback (GtkWidget *widget,
gpointer data)
{
EditLayerOptions *options;
GimpLayer *layer;
options = (EditLayerOptions *) data;
layer = options->layer;
if (options->gimage)
{
const gchar *new_name;
new_name = gtk_entry_get_text (GTK_ENTRY (options->name_entry));
if (strcmp (new_name, gimp_object_get_name (GIMP_OBJECT (layer))))
{
gimp_item_rename (GIMP_ITEM (layer), new_name);
gimp_image_flush (options->gimage);
}
}
gtk_widget_destroy (options->query_box);
}
void
layers_edit_layer_query (GimpLayer *layer)
{
EditLayerOptions *options;
GtkWidget *vbox;
GtkWidget *table;
options = g_new0 (EditLayerOptions, 1);
options->layer = layer;
options->gimage = gimp_item_get_image (GIMP_ITEM (layer));
/* The dialog */
options->query_box =
gimp_viewable_dialog_new (GIMP_VIEWABLE (layer),
_("Layer Attributes"),
"edit_layer_attributes",
GIMP_STOCK_EDIT,
_("Edit Layer Attributes"),
gimp_standard_help_func,
"dialogs/layers/edit_layer_attributes.html",
GTK_STOCK_CANCEL, gtk_widget_destroy,
NULL, 1, NULL, FALSE, TRUE,
GTK_STOCK_OK, edit_layer_query_ok_callback,
options, NULL, NULL, TRUE, FALSE,
NULL);
g_object_weak_ref (G_OBJECT (options->query_box),
(GWeakNotify) g_free,
options);
/* The main vbox */
vbox = gtk_vbox_new (FALSE, 4);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (options->query_box)->vbox),
vbox);
/* The name label and entry */
table = gtk_table_new (1, 2, FALSE);
gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4);
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
gtk_widget_show (table);
options->name_entry = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY (options->name_entry),
((gimp_layer_is_floating_sel (layer) ?
_("Floating Selection") :
gimp_object_get_name (GIMP_OBJECT (layer)))));
gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
_("Layer _Name"), 1.0, 0.5,
options->name_entry, 1, FALSE);
g_signal_connect (options->name_entry, "activate",
G_CALLBACK (edit_layer_query_ok_callback),
options);
gtk_widget_show (vbox);
gtk_widget_show (options->query_box);
}
/*******************************/
/* The add mask query dialog */
/*******************************/
typedef struct _AddMaskOptions AddMaskOptions;
struct _AddMaskOptions
{
GtkWidget *query_box;
GimpLayer *layer;
GimpAddMaskType add_mask_type;
gboolean invert;
};
static void
add_mask_query_ok_callback (GtkWidget *widget,
gpointer data)
{
AddMaskOptions *options;
GimpImage *gimage;
GimpLayerMask *mask;
GimpLayer *layer;
options = (AddMaskOptions *) data;
if ((layer = (options->layer)) && (gimage = GIMP_ITEM (layer)->gimage))
{
mask = gimp_layer_create_mask (layer, options->add_mask_type);
if (options->invert)
gimp_channel_invert (GIMP_CHANNEL (mask), FALSE);
gimp_layer_add_mask (layer, mask, TRUE);
g_object_unref (mask);
gimp_image_flush (gimage);
}
gtk_widget_destroy (options->query_box);
}
static void
layers_add_mask_query (GimpLayer *layer)
{
AddMaskOptions *options;
GtkWidget *frame;
GtkWidget *button;
GtkWidget *sep;
GimpImage *gimage;
/* The new options structure */
options = g_new (AddMaskOptions, 1);
options->layer = layer;
options->add_mask_type = GIMP_ADD_WHITE_MASK;
options->invert = FALSE;
gimage = gimp_item_get_image (GIMP_ITEM (layer));
/* The dialog */
options->query_box =
gimp_viewable_dialog_new (GIMP_VIEWABLE (layer),
_("Add Layer Mask"), "add_mask_options",
GTK_STOCK_ADD,
_("Add a Mask to the Layer"),
gimp_standard_help_func,
"dialogs/layers/add_layer_mask.html",
GTK_STOCK_CANCEL, gtk_widget_destroy,
NULL, 1, NULL, FALSE, TRUE,
GTK_STOCK_OK, add_mask_query_ok_callback,
options, NULL, NULL, TRUE, FALSE,
NULL);
g_object_weak_ref (G_OBJECT (options->query_box),
(GWeakNotify) g_free, options);
frame = gimp_enum_radio_frame_new (GIMP_TYPE_ADD_MASK_TYPE,
gtk_label_new (_("Initialize Layer Mask to:")),
6,
G_CALLBACK (gimp_radio_button_update),
&options->add_mask_type,
&button);
gimp_radio_group_set_active (GTK_RADIO_BUTTON (button),
GINT_TO_POINTER (options->add_mask_type));
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (options->query_box)->vbox),
frame);
gtk_widget_show (frame);
sep = gtk_hseparator_new ();
gtk_box_pack_start (GTK_BOX (GTK_BIN (frame)->child), sep, FALSE, FALSE, 0);
gtk_widget_show (sep);
button = gtk_check_button_new_with_mnemonic (_("In_vert Mask"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), options->invert);
g_signal_connect (button, "toggled",
G_CALLBACK (gimp_toggle_button_update),
&options->invert);
gtk_box_pack_end (GTK_BOX (GTK_BIN (frame)->child), button, FALSE, FALSE, 0);
gtk_widget_show (button);
gtk_widget_show (options->query_box);
}
/****************************/
/* The scale layer dialog */
/****************************/
typedef struct _ScaleLayerOptions ScaleLayerOptions;
struct _ScaleLayerOptions
{
GimpLayer *layer;
Resize *resize;
};
static void
scale_layer_query_ok_callback (GtkWidget *widget,
gpointer data)
{
ScaleLayerOptions *options;
GimpLayer *layer;
options = (ScaleLayerOptions *) data;
if (options->resize->width > 0 && options->resize->height > 0 &&
(layer = (options->layer)))
{
GimpImage *gimage;
gtk_widget_set_sensitive (options->resize->resize_shell, FALSE);
gimage = gimp_item_get_image (GIMP_ITEM (layer));
if (gimage)
{
gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_LAYER_SCALE,
_("Scale Layer"));
if (gimp_layer_is_floating_sel (layer))
floating_sel_relax (layer, TRUE);
gimp_layer_scale (layer,
options->resize->width,
options->resize->height,
options->resize->interpolation,
TRUE);
if (gimp_layer_is_floating_sel (layer))
floating_sel_rigor (layer, TRUE);
gimp_image_undo_group_end (gimage);
gimp_image_flush (gimage);
}
gtk_widget_destroy (options->resize->resize_shell);
}
else
{
g_message (_("Invalid width or height.\n"
"Both must be positive."));
}
}
static void
layers_scale_layer_query (GimpImage *gimage,
GimpLayer *layer)
{
ScaleLayerOptions *options;
options = g_new0 (ScaleLayerOptions, 1);
options->layer = layer;
options->resize =
resize_widget_new (GIMP_VIEWABLE (layer),
ScaleWidget,
gimp_drawable_width (GIMP_DRAWABLE (layer)),
gimp_drawable_height (GIMP_DRAWABLE (layer)),
gimage->xresolution,
gimage->yresolution,
gimage->unit,
TRUE,
G_CALLBACK (scale_layer_query_ok_callback),
options);
g_object_weak_ref (G_OBJECT (options->resize->resize_shell),
(GWeakNotify) g_free,
options);
gtk_widget_show (options->resize->resize_shell);
}
/*****************************/
/* The resize layer dialog */
/*****************************/
typedef struct _ResizeLayerOptions ResizeLayerOptions;
struct _ResizeLayerOptions
{
GimpLayer *layer;
Resize *resize;
};
static void
resize_layer_query_ok_callback (GtkWidget *widget,
gpointer data)
{
ResizeLayerOptions *options;
GimpLayer *layer;
options = (ResizeLayerOptions *) data;
if (options->resize->width > 0 && options->resize->height > 0 &&
(layer = (options->layer)))
{
GimpImage *gimage;
gtk_widget_set_sensitive (options->resize->resize_shell, FALSE);
gimage = gimp_item_get_image (GIMP_ITEM (layer));
if (gimage)
{
gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_LAYER_RESIZE,
_("Resize Layer"));
if (gimp_layer_is_floating_sel (layer))
floating_sel_relax (layer, TRUE);
gimp_layer_resize (layer,
options->resize->width,
options->resize->height,
options->resize->offset_x,
options->resize->offset_y);
if (gimp_layer_is_floating_sel (layer))
floating_sel_rigor (layer, TRUE);
gimp_image_undo_group_end (gimage);
gimp_image_flush (gimage);
}
gtk_widget_destroy (options->resize->resize_shell);
}
else
{
g_message (_("Invalid width or height.\n"
"Both must be positive."));
}
}
static void
layers_resize_layer_query (GimpImage *gimage,
GimpLayer *layer)
{
ResizeLayerOptions *options;
options = g_new0 (ResizeLayerOptions, 1);
options->layer = layer;
options->resize =
resize_widget_new (GIMP_VIEWABLE (layer),
ResizeWidget,
gimp_drawable_width (GIMP_DRAWABLE (layer)),
gimp_drawable_height (GIMP_DRAWABLE (layer)),
gimage->xresolution,
gimage->yresolution,
gimage->unit,
TRUE,
G_CALLBACK (resize_layer_query_ok_callback),
options);
g_object_weak_ref (G_OBJECT (options->resize->resize_shell),
(GWeakNotify) g_free,
options);
gtk_widget_show (options->resize->resize_shell);
}