mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-07-03 17:33:25 +00:00

2004-10-18 Michael Natterer <mitch@gimp.org> Action code review and pre-release consistency cleanup: * app/actions/*-actions.c: added some missing and resolved conflicting mnemonics, added missing help IDs. Cleaned up the *_actions_update() functions. * app/actions/channels-actions.c * app/actions/layers-actions.c * app/actions/vectors-actions.c (*_actions_update): simplified the code that figures the prev and next channel,layer,vectors. * app/actions/qmask-actions.c: use the same accelerator for "qmask-active" and "qmask-toggle". Fixed action sensitivity. * app/actions/channels-commands.c * app/actions/dockable-commands.c * app/actions/documents-commands.c * app/actions/gradients-commands.c * app/actions/layers-commands.c * app/actions/palettes-commands.c * app/actions/image-commands.c * app/actions/select-commands.c * app/actions/vectors-commands.c: folded tons of private utility functions into their only callers (they used to be public and called from outside before the switch to action based menus). Renamed functions and variables saying "query" or "qbox" to "dialog". Moved static functions to the end of the files. Misc minor cleanups. * app/actions/drawable-actions.c * app/actions/drawable-commands.c: made the "drawable-visible" and "drawable-linked" actions affect the layer if the active drawable is a layer mask. * app/actions/select-commands.c: added action to stroke with the last values used in an attempt to address bug #135746 but #if 0'ed it because the approach is too ugly. * app/tools/gimpiscissorstool.c: changed mnemonic from I to S. * menus/image-menu-xml.in: added more stuff to the (commented out) "context" menu.
692 lines
20 KiB
C
692 lines
20 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 <gtk/gtk.h>
|
|
|
|
#include "libgimpbase/gimpbase.h"
|
|
#include "libgimpwidgets/gimpwidgets.h"
|
|
|
|
#include "actions-types.h"
|
|
|
|
#include "config/gimpguiconfig.h"
|
|
|
|
#include "core/core-enums.h"
|
|
#include "core/gimp.h"
|
|
#include "core/gimpchannel.h"
|
|
#include "core/gimpcontext.h"
|
|
#include "core/gimpimage.h"
|
|
#include "core/gimpimage-convert.h"
|
|
#include "core/gimpimage-crop.h"
|
|
#include "core/gimpimage-duplicate.h"
|
|
#include "core/gimpimage-flip.h"
|
|
#include "core/gimpimage-merge.h"
|
|
#include "core/gimpimage-resize.h"
|
|
#include "core/gimpimage-rotate.h"
|
|
#include "core/gimpimage-scale.h"
|
|
#include "core/gimpimage-undo.h"
|
|
#include "core/gimpprogress.h"
|
|
|
|
#include "widgets/gimpdialogfactory.h"
|
|
#include "widgets/gimpdock.h"
|
|
#include "widgets/gimphelp-ids.h"
|
|
#include "widgets/gimpmessagebox.h"
|
|
#include "widgets/gimpmessagedialog.h"
|
|
#include "widgets/gimpviewabledialog.h"
|
|
|
|
#include "display/gimpdisplay.h"
|
|
#include "display/gimpdisplayshell.h"
|
|
|
|
#include "dialogs/convert-dialog.h"
|
|
#include "dialogs/dialogs.h"
|
|
#include "dialogs/grid-dialog.h"
|
|
#include "dialogs/image-new-dialog.h"
|
|
#include "dialogs/resize-dialog.h"
|
|
|
|
#include "actions.h"
|
|
#include "image-commands.h"
|
|
|
|
#include "gimp-intl.h"
|
|
|
|
|
|
typedef struct _ImageResizeOptions ImageResizeOptions;
|
|
|
|
struct _ImageResizeOptions
|
|
{
|
|
ResizeDialog *dialog;
|
|
|
|
GimpContext *context;
|
|
GimpDisplay *gdisp;
|
|
GimpImage *gimage;
|
|
};
|
|
|
|
|
|
typedef struct _LayerMergeOptions LayerMergeOptions;
|
|
|
|
struct _LayerMergeOptions
|
|
{
|
|
GimpContext *context;
|
|
GimpImage *gimage;
|
|
GimpMergeType merge_type;
|
|
};
|
|
|
|
|
|
/* local function prototypes */
|
|
|
|
static void image_resize_callback (GtkWidget *widget,
|
|
gpointer data);
|
|
static void image_scale_callback (GtkWidget *widget,
|
|
gpointer data);
|
|
static void image_scale_confirm_large (ImageResizeOptions *options,
|
|
gint64 new_memsize,
|
|
gint64 max_memsize);
|
|
static void image_scale_confirm_small (ImageResizeOptions *options);
|
|
static void image_scale_confirm_response (GtkWidget *widget,
|
|
gint response_id,
|
|
ImageResizeOptions *options);
|
|
static void image_scale_implement (ImageResizeOptions *options);
|
|
static void image_merge_layers_response (GtkWidget *dialog,
|
|
gint response_id,
|
|
LayerMergeOptions *options);
|
|
|
|
|
|
/* public functions */
|
|
|
|
void
|
|
image_new_cmd_callback (GtkAction *action,
|
|
gpointer data)
|
|
{
|
|
GtkWidget *widget;
|
|
GtkWidget *dialog;
|
|
return_if_no_widget (widget, data);
|
|
|
|
dialog = gimp_dialog_factory_dialog_new (global_dialog_factory,
|
|
gtk_widget_get_screen (widget),
|
|
"gimp-image-new-dialog", -1, FALSE);
|
|
|
|
if (dialog)
|
|
{
|
|
image_new_dialog_set (dialog, NULL, NULL);
|
|
|
|
gtk_window_present (GTK_WINDOW (dialog));
|
|
}
|
|
}
|
|
|
|
void
|
|
image_new_from_image_cmd_callback (GtkAction *action,
|
|
gpointer data)
|
|
{
|
|
GtkWidget *widget;
|
|
GtkWidget *dialog;
|
|
return_if_no_widget (widget, data);
|
|
|
|
dialog = gimp_dialog_factory_dialog_new (global_dialog_factory,
|
|
gtk_widget_get_screen (widget),
|
|
"gimp-image-new-dialog", -1, FALSE);
|
|
|
|
if (dialog)
|
|
{
|
|
GimpImage *gimage = action_data_get_image (data);
|
|
|
|
if (gimage)
|
|
image_new_dialog_set (dialog, gimage, NULL);
|
|
|
|
gtk_window_present (GTK_WINDOW (dialog));
|
|
}
|
|
}
|
|
|
|
void
|
|
image_convert_cmd_callback (GtkAction *action,
|
|
gint value,
|
|
gpointer data)
|
|
{
|
|
GimpImage *gimage;
|
|
GtkWidget *widget;
|
|
GimpDisplay *gdisp;
|
|
return_if_no_image (gimage, data);
|
|
return_if_no_widget (widget, data);
|
|
return_if_no_display (gdisp, data);
|
|
|
|
switch ((GimpImageBaseType) value)
|
|
{
|
|
case GIMP_RGB:
|
|
case GIMP_GRAY:
|
|
gimp_image_convert (gimage, (GimpImageBaseType) value,
|
|
0, 0, FALSE, FALSE, 0, NULL, NULL);
|
|
gimp_image_flush (gimage);
|
|
break;
|
|
|
|
case GIMP_INDEXED:
|
|
gtk_widget_show (convert_dialog_new (gimage, widget,
|
|
GIMP_PROGRESS (gdisp)));
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
image_resize_cmd_callback (GtkAction *action,
|
|
gpointer data)
|
|
{
|
|
ImageResizeOptions *options;
|
|
GimpDisplay *gdisp;
|
|
GimpImage *gimage;
|
|
return_if_no_display (gdisp, data);
|
|
|
|
gimage = gdisp->gimage;
|
|
|
|
options = g_new0 (ImageResizeOptions, 1);
|
|
|
|
options->context = action_data_get_context (data);
|
|
options->gdisp = gdisp;
|
|
options->gimage = gimage;
|
|
|
|
options->dialog =
|
|
resize_dialog_new (GIMP_VIEWABLE (gimage), gdisp->shell,
|
|
RESIZE_DIALOG,
|
|
gimage->width,
|
|
gimage->height,
|
|
gimage->xresolution,
|
|
gimage->yresolution,
|
|
GIMP_DISPLAY_SHELL (gdisp->shell)->unit,
|
|
G_CALLBACK (image_resize_callback),
|
|
options);
|
|
|
|
g_signal_connect_object (gdisp, "disconnect",
|
|
G_CALLBACK (gtk_widget_destroy),
|
|
options->dialog->shell,
|
|
G_CONNECT_SWAPPED);
|
|
|
|
g_object_weak_ref (G_OBJECT (options->dialog->shell),
|
|
(GWeakNotify) g_free,
|
|
options);
|
|
|
|
gtk_widget_show (options->dialog->shell);
|
|
}
|
|
|
|
void
|
|
image_resize_to_layers_cmd_callback (GtkAction *action,
|
|
gpointer data)
|
|
{
|
|
GimpDisplay *gdisp;
|
|
GimpProgress *progress;
|
|
|
|
return_if_no_display (gdisp, data);
|
|
|
|
progress = gimp_progress_start (GIMP_PROGRESS (gdisp),
|
|
_("Resizing..."), FALSE);
|
|
|
|
gimp_image_resize_to_layers (gdisp->gimage,
|
|
action_data_get_context (data),
|
|
progress);
|
|
|
|
if (progress)
|
|
gimp_progress_end (progress);
|
|
|
|
gimp_image_flush (gdisp->gimage);
|
|
}
|
|
|
|
void
|
|
image_scale_cmd_callback (GtkAction *action,
|
|
gpointer data)
|
|
{
|
|
ImageResizeOptions *options;
|
|
GimpDisplay *gdisp;
|
|
GimpImage *gimage;
|
|
return_if_no_display (gdisp, data);
|
|
|
|
gimage = gdisp->gimage;
|
|
|
|
options = g_new0 (ImageResizeOptions, 1);
|
|
|
|
options->context = action_data_get_context (data);
|
|
options->gdisp = gdisp;
|
|
options->gimage = gimage;
|
|
|
|
options->dialog =
|
|
resize_dialog_new (GIMP_VIEWABLE (gimage), gdisp->shell,
|
|
SCALE_DIALOG,
|
|
gimage->width,
|
|
gimage->height,
|
|
gimage->xresolution,
|
|
gimage->yresolution,
|
|
GIMP_DISPLAY_SHELL (gdisp->shell)->unit,
|
|
G_CALLBACK (image_scale_callback),
|
|
options);
|
|
|
|
g_signal_connect_object (gdisp, "disconnect",
|
|
G_CALLBACK (gtk_widget_destroy),
|
|
options->dialog->shell,
|
|
G_CONNECT_SWAPPED);
|
|
|
|
g_object_weak_ref (G_OBJECT (options->dialog->shell),
|
|
(GWeakNotify) g_free,
|
|
options);
|
|
|
|
gtk_widget_show (options->dialog->shell);
|
|
}
|
|
|
|
void
|
|
image_flip_cmd_callback (GtkAction *action,
|
|
gint value,
|
|
gpointer data)
|
|
{
|
|
GimpDisplay *gdisp;
|
|
GimpProgress *progress;
|
|
return_if_no_display (gdisp, data);
|
|
|
|
progress = gimp_progress_start (GIMP_PROGRESS (gdisp),
|
|
_("Flipping..."), FALSE);
|
|
|
|
gimp_image_flip (gdisp->gimage, action_data_get_context (data),
|
|
(GimpOrientationType) value, progress);
|
|
|
|
if (progress)
|
|
gimp_progress_end (progress);
|
|
|
|
gimp_image_flush (gdisp->gimage);
|
|
}
|
|
|
|
void
|
|
image_rotate_cmd_callback (GtkAction *action,
|
|
gint value,
|
|
gpointer data)
|
|
{
|
|
GimpDisplay *gdisp;
|
|
GimpProgress *progress;
|
|
return_if_no_display (gdisp, data);
|
|
|
|
progress = gimp_progress_start (GIMP_PROGRESS (gdisp),
|
|
_("Rotating..."), FALSE);
|
|
|
|
gimp_image_rotate (gdisp->gimage, action_data_get_context (data),
|
|
(GimpRotationType) value, progress);
|
|
|
|
if (progress)
|
|
gimp_progress_end (progress);
|
|
|
|
gimp_image_flush (gdisp->gimage);
|
|
}
|
|
|
|
void
|
|
image_crop_cmd_callback (GtkAction *action,
|
|
gpointer data)
|
|
{
|
|
GimpImage *gimage;
|
|
gint x1, y1, x2, y2;
|
|
return_if_no_image (gimage, data);
|
|
|
|
if (! gimp_channel_bounds (gimp_image_get_mask (gimage),
|
|
&x1, &y1, &x2, &y2))
|
|
{
|
|
g_message (_("Cannot crop because the current selection is empty."));
|
|
return;
|
|
}
|
|
|
|
gimp_image_crop (gimage, action_data_get_context (data),
|
|
x1, y1, x2, y2, FALSE, TRUE);
|
|
gimp_image_flush (gimage);
|
|
}
|
|
|
|
void
|
|
image_duplicate_cmd_callback (GtkAction *action,
|
|
gpointer data)
|
|
{
|
|
GimpDisplay *gdisp;
|
|
GimpDisplayShell *shell;
|
|
GimpImage *new_gimage;
|
|
return_if_no_display (gdisp, data);
|
|
|
|
shell = GIMP_DISPLAY_SHELL (gdisp->shell);
|
|
|
|
new_gimage = gimp_image_duplicate (gdisp->gimage);
|
|
|
|
gimp_create_display (new_gimage->gimp,
|
|
new_gimage,
|
|
shell->unit, shell->scale);
|
|
|
|
g_object_unref (new_gimage);
|
|
}
|
|
|
|
void
|
|
image_merge_layers_cmd_callback (GtkAction *action,
|
|
gpointer data)
|
|
{
|
|
LayerMergeOptions *options;
|
|
GimpImage *gimage;
|
|
GtkWidget *dialog;
|
|
GtkWidget *widget;
|
|
GtkWidget *frame;
|
|
return_if_no_image (gimage, data);
|
|
return_if_no_widget (widget, data);
|
|
|
|
options = g_new0 (LayerMergeOptions, 1);
|
|
|
|
options->context = action_data_get_context (data);
|
|
options->gimage = gimage;
|
|
options->merge_type = GIMP_EXPAND_AS_NECESSARY;
|
|
|
|
dialog = gimp_viewable_dialog_new (GIMP_VIEWABLE (gimage),
|
|
_("Merge Layers"),
|
|
"gimp-image-merge-layers",
|
|
GIMP_STOCK_MERGE_DOWN,
|
|
_("Layers Merge Options"),
|
|
widget,
|
|
gimp_standard_help_func,
|
|
GIMP_HELP_IMAGE_MERGE_LAYERS,
|
|
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
GTK_STOCK_OK, GTK_RESPONSE_OK,
|
|
|
|
NULL);
|
|
|
|
g_signal_connect (dialog, "response",
|
|
G_CALLBACK (image_merge_layers_response),
|
|
options);
|
|
|
|
frame = gimp_int_radio_group_new (TRUE, _("Final, Merged Layer should be:"),
|
|
G_CALLBACK (gimp_radio_button_update),
|
|
&options->merge_type, options->merge_type,
|
|
|
|
_("Expanded as necessary"),
|
|
GIMP_EXPAND_AS_NECESSARY, NULL,
|
|
|
|
_("Clipped to image"),
|
|
GIMP_CLIP_TO_IMAGE, NULL,
|
|
|
|
_("Clipped to bottom layer"),
|
|
GIMP_CLIP_TO_BOTTOM_LAYER, NULL,
|
|
|
|
NULL);
|
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (frame), 12);
|
|
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), frame);
|
|
gtk_widget_show (frame);
|
|
|
|
gtk_widget_show (dialog);
|
|
}
|
|
|
|
void
|
|
image_flatten_image_cmd_callback (GtkAction *action,
|
|
gpointer data)
|
|
{
|
|
GimpImage *gimage;
|
|
return_if_no_image (gimage, data);
|
|
|
|
gimp_image_flatten (gimage, action_data_get_context (data));
|
|
gimp_image_flush (gimage);
|
|
}
|
|
|
|
void
|
|
image_configure_grid_cmd_callback (GtkAction *action,
|
|
gpointer data)
|
|
{
|
|
GimpDisplay *gdisp;
|
|
GimpDisplayShell *shell;
|
|
GimpImage *gimage;
|
|
return_if_no_display (gdisp, data);
|
|
|
|
shell = GIMP_DISPLAY_SHELL (gdisp->shell);
|
|
gimage = gdisp->gimage;
|
|
|
|
if (! shell->grid_dialog)
|
|
{
|
|
shell->grid_dialog = grid_dialog_new (gdisp->gimage, gdisp->shell);
|
|
|
|
gtk_window_set_transient_for (GTK_WINDOW (shell->grid_dialog),
|
|
GTK_WINDOW (gdisp->shell));
|
|
gtk_window_set_destroy_with_parent (GTK_WINDOW (shell->grid_dialog),
|
|
TRUE);
|
|
|
|
g_object_add_weak_pointer (G_OBJECT (shell->grid_dialog),
|
|
(gpointer *) &shell->grid_dialog);
|
|
}
|
|
|
|
gtk_window_present (GTK_WINDOW (shell->grid_dialog));
|
|
}
|
|
|
|
|
|
/* private functions */
|
|
|
|
static void
|
|
image_resize_callback (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
ImageResizeOptions *options = data;
|
|
|
|
gtk_widget_set_sensitive (options->dialog->shell, FALSE);
|
|
|
|
if (options->dialog->width > 0 &&
|
|
options->dialog->height > 0)
|
|
{
|
|
GimpProgress *progress;
|
|
|
|
progress = gimp_progress_start (GIMP_PROGRESS (options->gdisp),
|
|
_("Resizing..."), FALSE);
|
|
|
|
gimp_image_resize (options->gimage,
|
|
options->context,
|
|
options->dialog->width,
|
|
options->dialog->height,
|
|
options->dialog->offset_x,
|
|
options->dialog->offset_y,
|
|
progress);
|
|
|
|
if (progress)
|
|
gimp_progress_end (progress);
|
|
|
|
gimp_image_flush (options->gimage);
|
|
}
|
|
else
|
|
{
|
|
g_message (_("Resize Error: Both width and height must be "
|
|
"greater than zero."));
|
|
}
|
|
|
|
gtk_widget_destroy (options->dialog->shell);
|
|
}
|
|
|
|
static void
|
|
image_scale_callback (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
ImageResizeOptions *options = data;
|
|
GimpImageScaleCheckType scale_check;
|
|
gint64 max_memsize;
|
|
gint64 new_memsize;
|
|
|
|
gtk_widget_set_sensitive (options->dialog->shell, FALSE);
|
|
|
|
max_memsize =
|
|
GIMP_GUI_CONFIG (options->gimage->gimp->config)->max_new_image_size;
|
|
|
|
scale_check = gimp_image_scale_check (options->gimage,
|
|
options->dialog->width,
|
|
options->dialog->height,
|
|
max_memsize,
|
|
&new_memsize);
|
|
switch (scale_check)
|
|
{
|
|
case GIMP_IMAGE_SCALE_TOO_BIG:
|
|
image_scale_confirm_large (options, new_memsize, max_memsize);
|
|
break;
|
|
|
|
case GIMP_IMAGE_SCALE_TOO_SMALL:
|
|
image_scale_confirm_small (options);
|
|
break;
|
|
|
|
case GIMP_IMAGE_SCALE_OK:
|
|
/* If all is well, return directly after scaling image. */
|
|
image_scale_implement (options);
|
|
gtk_widget_destroy (options->dialog->shell);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static GtkWidget *
|
|
image_scale_confirm_dialog (ImageResizeOptions *options)
|
|
{
|
|
GtkWidget *dialog;
|
|
|
|
dialog = gimp_message_dialog_new (_("Confirm Scaling"),
|
|
GIMP_STOCK_WARNING,
|
|
options->dialog->shell,
|
|
GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
gimp_standard_help_func,
|
|
GIMP_HELP_IMAGE_SCALE_WARNING,
|
|
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
GIMP_STOCK_SCALE, GTK_RESPONSE_OK,
|
|
|
|
NULL);
|
|
|
|
g_signal_connect (dialog, "response",
|
|
G_CALLBACK (image_scale_confirm_response),
|
|
options);
|
|
|
|
return dialog;
|
|
}
|
|
|
|
static void
|
|
image_scale_confirm_large (ImageResizeOptions *options,
|
|
gint64 new_memsize,
|
|
gint64 max_memsize)
|
|
{
|
|
GtkWidget *dialog = image_scale_confirm_dialog (options);
|
|
gchar *size;
|
|
|
|
size = gimp_memsize_to_string (new_memsize);
|
|
gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
|
|
_("You are trying to create an image "
|
|
"with a size of %s."), size);
|
|
g_free (size);
|
|
|
|
size = gimp_memsize_to_string (max_memsize);
|
|
gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (dialog)->box,
|
|
_("Scaling the image to the choosen size will "
|
|
"make it use more memory than what is "
|
|
"configured as \"Maximum Image Size\" in the "
|
|
"Preferences dialog (currently %s)."), size);
|
|
g_free (size);
|
|
|
|
gtk_widget_show (dialog);
|
|
}
|
|
|
|
static void
|
|
image_scale_confirm_small (ImageResizeOptions *options)
|
|
{
|
|
GtkWidget *dialog = image_scale_confirm_dialog (options);
|
|
|
|
gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
|
|
_("Scaling the image to the choosen size "
|
|
"will shrink some layers completely "
|
|
"away."));
|
|
gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (dialog)->box,
|
|
_("Is this what you want to do?"));
|
|
|
|
gtk_widget_show (dialog);
|
|
}
|
|
|
|
static void
|
|
image_scale_confirm_response (GtkWidget *dialog,
|
|
gint response_id,
|
|
ImageResizeOptions *options)
|
|
{
|
|
gtk_widget_destroy (dialog);
|
|
|
|
if (response_id == GTK_RESPONSE_OK)
|
|
{
|
|
image_scale_implement (options);
|
|
gtk_widget_destroy (options->dialog->shell);
|
|
}
|
|
else
|
|
{
|
|
gtk_widget_set_sensitive (options->dialog->shell, TRUE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
image_scale_implement (ImageResizeOptions *options)
|
|
{
|
|
GimpImage *gimage = options->gimage;
|
|
|
|
if (options->dialog->resolution_x == gimage->xresolution &&
|
|
options->dialog->resolution_y == gimage->yresolution &&
|
|
options->dialog->unit == gimage->resolution_unit &&
|
|
options->dialog->width == gimage->width &&
|
|
options->dialog->height == gimage->height)
|
|
return;
|
|
|
|
gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_IMAGE_SCALE,
|
|
_("Scale Image"));
|
|
|
|
gimp_image_set_resolution (gimage,
|
|
options->dialog->resolution_x,
|
|
options->dialog->resolution_y);
|
|
gimp_image_set_unit (gimage, options->dialog->unit);
|
|
|
|
if (options->dialog->width != gimage->width ||
|
|
options->dialog->height != gimage->height)
|
|
{
|
|
if (options->dialog->width > 0 &&
|
|
options->dialog->height > 0)
|
|
{
|
|
GimpProgress *progress;
|
|
|
|
progress = gimp_progress_start (GIMP_PROGRESS (options->gdisp),
|
|
_("Scaling..."), FALSE);
|
|
|
|
gimp_image_scale (gimage,
|
|
options->dialog->width,
|
|
options->dialog->height,
|
|
options->dialog->interpolation,
|
|
progress);
|
|
|
|
if (progress)
|
|
gimp_progress_end (progress);
|
|
}
|
|
else
|
|
{
|
|
g_message (_("Scale Error: Both width and height must be "
|
|
"greater than zero."));
|
|
return;
|
|
}
|
|
}
|
|
|
|
gimp_image_undo_group_end (gimage);
|
|
|
|
gimp_image_flush (gimage);
|
|
}
|
|
|
|
static void
|
|
image_merge_layers_response (GtkWidget *dialog,
|
|
gint response_id,
|
|
LayerMergeOptions *options)
|
|
{
|
|
gtk_widget_destroy (dialog);
|
|
|
|
if (response_id == GTK_RESPONSE_OK)
|
|
{
|
|
gimp_image_merge_visible_layers (options->gimage,
|
|
options->context,
|
|
options->merge_type);
|
|
gimp_image_flush (options->gimage);
|
|
}
|
|
|
|
g_free (options);
|
|
}
|