diff options
Diffstat (limited to 'app/dialogs/print-size-dialog.c')
-rw-r--r-- | app/dialogs/print-size-dialog.c | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/app/dialogs/print-size-dialog.c b/app/dialogs/print-size-dialog.c new file mode 100644 index 0000000..e3b9ba0 --- /dev/null +++ b/app/dialogs/print-size-dialog.c @@ -0,0 +1,454 @@ +/* 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 <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <gegl.h> +#include <gtk/gtk.h> + +#include "libgimpbase/gimpbase.h" +#include "libgimpwidgets/gimpwidgets.h" + +#include "dialogs-types.h" + +#include "core/gimpcontext.h" +#include "core/gimpimage.h" +#include "core/gimp-utils.h" + +#include "widgets/gimphelp-ids.h" +#include "widgets/gimpviewabledialog.h" + +#include "print-size-dialog.h" + +#include "gimp-intl.h" + + +#define RESPONSE_RESET 1 +#define SB_WIDTH 8 + + +typedef struct _PrintSizeDialog PrintSizeDialog; + +struct _PrintSizeDialog +{ + GimpImage *image; + GimpSizeEntry *size_entry; + GimpSizeEntry *resolution_entry; + GimpChainButton *chain; + gdouble xres; + gdouble yres; + GimpResolutionCallback callback; + gpointer user_data; +}; + + +/* local function prototypes */ + +static void print_size_dialog_free (PrintSizeDialog *private); +static void print_size_dialog_response (GtkWidget *dialog, + gint response_id, + PrintSizeDialog *private); +static void print_size_dialog_reset (PrintSizeDialog *private); + +static void print_size_dialog_size_changed (GtkWidget *widget, + PrintSizeDialog *private); +static void print_size_dialog_resolution_changed (GtkWidget *widget, + PrintSizeDialog *private); +static void print_size_dialog_set_size (PrintSizeDialog *private, + gdouble width, + gdouble height); +static void print_size_dialog_set_resolution (PrintSizeDialog *private, + gdouble xres, + gdouble yres); + + +/* public functions */ + +GtkWidget * +print_size_dialog_new (GimpImage *image, + GimpContext *context, + const gchar *title, + const gchar *role, + GtkWidget *parent, + GimpHelpFunc help_func, + const gchar *help_id, + GimpResolutionCallback callback, + gpointer user_data) +{ + PrintSizeDialog *private; + GtkWidget *dialog; + GtkWidget *frame; + GtkWidget *table; + GtkWidget *entry; + GtkWidget *label; + GtkWidget *width; + GtkWidget *height; + GtkWidget *hbox; + GtkWidget *chain; + GtkAdjustment *adj; + GList *focus_chain = NULL; + + g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); + g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); + g_return_val_if_fail (callback != NULL, NULL); + + private = g_slice_new0 (PrintSizeDialog); + + private->image = image; + private->callback = callback; + private->user_data = user_data; + + gimp_image_get_resolution (image, &private->xres, &private->yres); + + dialog = gimp_viewable_dialog_new (GIMP_VIEWABLE (image), context, + title, role, + GIMP_ICON_DOCUMENT_PRINT_RESOLUTION, title, + parent, + help_func, help_id, + + _("_Reset"), RESPONSE_RESET, + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_OK"), GTK_RESPONSE_OK, + + NULL); + + gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), + RESPONSE_RESET, + GTK_RESPONSE_OK, + GTK_RESPONSE_CANCEL, + -1); + + gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); + + g_object_weak_ref (G_OBJECT (dialog), + (GWeakNotify) print_size_dialog_free, private); + + g_signal_connect (dialog, "response", + G_CALLBACK (print_size_dialog_response), + private); + + frame = gimp_frame_new (_("Print Size")); + gtk_container_set_border_width (GTK_CONTAINER (frame), 12); + gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), + frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + table = gtk_table_new (4, 3, FALSE); + gtk_table_set_col_spacing (GTK_TABLE (table), 0, 6); + gtk_table_set_row_spacings (GTK_TABLE (table), 12); + gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2); + gtk_table_set_row_spacing (GTK_TABLE (table), 2, 2); + gtk_container_add (GTK_CONTAINER (frame), table); + gtk_widget_show (table); + + /* the print size entry */ + + adj = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0); + width = gimp_spin_button_new (adj, 1.0, 2); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (width), TRUE); + gtk_entry_set_width_chars (GTK_ENTRY (width), SB_WIDTH); + + adj = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0); + height = gimp_spin_button_new (adj, 1.0, 2); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (height), TRUE); + gtk_entry_set_width_chars (GTK_ENTRY (height), SB_WIDTH); + + entry = gimp_size_entry_new (0, gimp_get_default_unit (), "%p", + FALSE, FALSE, FALSE, SB_WIDTH, + GIMP_SIZE_ENTRY_UPDATE_SIZE); + private->size_entry = GIMP_SIZE_ENTRY (entry); + + label = gtk_label_new_with_mnemonic (_("_Width:")); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), width); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (label); + + label = gtk_label_new_with_mnemonic (_("H_eight:")); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), height); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (label); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_table_attach_defaults (GTK_TABLE (table), hbox, 1, 2, 0, 2); + gtk_widget_show (hbox); + + gtk_table_set_row_spacing (GTK_TABLE (entry), 0, 2); + gtk_table_set_col_spacing (GTK_TABLE (entry), 1, 6); + + gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0); + gtk_widget_show (entry); + + gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry), + GTK_SPIN_BUTTON (height), NULL); + gtk_table_attach_defaults (GTK_TABLE (entry), height, 0, 1, 1, 2); + gtk_widget_show (height); + + gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry), + GTK_SPIN_BUTTON (width), NULL); + gtk_table_attach_defaults (GTK_TABLE (entry), width, 0, 1, 0, 1); + gtk_widget_show (width); + + gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (entry), 0, + private->xres, FALSE); + gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (entry), 1, + private->yres, FALSE); + + gimp_size_entry_set_refval_boundaries + (GIMP_SIZE_ENTRY (entry), 0, GIMP_MIN_IMAGE_SIZE, GIMP_MAX_IMAGE_SIZE); + gimp_size_entry_set_refval_boundaries + (GIMP_SIZE_ENTRY (entry), 1, GIMP_MIN_IMAGE_SIZE, GIMP_MAX_IMAGE_SIZE); + + gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (entry), 0, + gimp_image_get_width (image)); + gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (entry), 1, + gimp_image_get_height (image)); + + /* the resolution entry */ + + adj = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0); + width = gimp_spin_button_new (adj, 1.0, 2); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (width), TRUE); + gtk_entry_set_width_chars (GTK_ENTRY (width), SB_WIDTH); + + adj = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0); + height = gimp_spin_button_new (adj, 1.0, 2); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (height), TRUE); + gtk_entry_set_width_chars (GTK_ENTRY (height), SB_WIDTH); + + label = gtk_label_new_with_mnemonic (_("_X resolution:")); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), width); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (label); + + label = gtk_label_new_with_mnemonic (_("_Y resolution:")); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), height); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (label); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_table_attach_defaults (GTK_TABLE (table), hbox, 1, 2, 2, 4); + gtk_widget_show (hbox); + + entry = gimp_size_entry_new (0, gimp_image_get_unit (image), _("pixels/%a"), + FALSE, FALSE, FALSE, SB_WIDTH, + GIMP_SIZE_ENTRY_UPDATE_RESOLUTION); + private->resolution_entry = GIMP_SIZE_ENTRY (entry); + + gtk_table_set_row_spacing (GTK_TABLE (entry), 0, 2); + gtk_table_set_col_spacing (GTK_TABLE (entry), 1, 2); + gtk_table_set_col_spacing (GTK_TABLE (entry), 2, 2); + + gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0); + gtk_widget_show (entry); + + gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry), + GTK_SPIN_BUTTON (height), NULL); + gtk_table_attach_defaults (GTK_TABLE (entry), height, 0, 1, 1, 2); + gtk_widget_show (height); + + gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry), + GTK_SPIN_BUTTON (width), NULL); + gtk_table_attach_defaults (GTK_TABLE (entry), width, 0, 1, 0, 1); + gtk_widget_show (width); + + gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (entry), 0, + GIMP_MIN_RESOLUTION, + GIMP_MAX_RESOLUTION); + gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (entry), 1, + GIMP_MIN_RESOLUTION, + GIMP_MAX_RESOLUTION); + + gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (entry), 0, private->xres); + gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (entry), 1, private->yres); + + chain = gimp_chain_button_new (GIMP_CHAIN_RIGHT); + if (ABS (private->xres - private->yres) < GIMP_MIN_RESOLUTION) + gimp_chain_button_set_active (GIMP_CHAIN_BUTTON (chain), TRUE); + gtk_table_attach_defaults (GTK_TABLE (entry), chain, 1, 2, 0, 2); + gtk_widget_show (chain); + + private->chain = GIMP_CHAIN_BUTTON (chain); + + focus_chain = g_list_prepend (focus_chain, GIMP_SIZE_ENTRY (entry)->unitmenu); + focus_chain = g_list_prepend (focus_chain, chain); + focus_chain = g_list_prepend (focus_chain, height); + focus_chain = g_list_prepend (focus_chain, width); + + gtk_container_set_focus_chain (GTK_CONTAINER (entry), focus_chain); + g_list_free (focus_chain); + + g_signal_connect (private->size_entry, "value-changed", + G_CALLBACK (print_size_dialog_size_changed), + private); + g_signal_connect (private->resolution_entry, "value-changed", + G_CALLBACK (print_size_dialog_resolution_changed), + private); + + return dialog; +} + + +/* private functions */ + +static void +print_size_dialog_free (PrintSizeDialog *private) +{ + g_slice_free (PrintSizeDialog, private); +} + +static void +print_size_dialog_response (GtkWidget *dialog, + gint response_id, + PrintSizeDialog *private) +{ + GimpSizeEntry *entry = private->resolution_entry; + + switch (response_id) + { + case RESPONSE_RESET: + print_size_dialog_reset (private); + break; + + case GTK_RESPONSE_OK: + private->callback (dialog, + private->image, + gimp_size_entry_get_refval (entry, 0), + gimp_size_entry_get_refval (entry, 1), + gimp_size_entry_get_unit (entry), + private->user_data); + break; + + default: + gtk_widget_destroy (dialog); + break; + } +} + +static void +print_size_dialog_reset (PrintSizeDialog *private) +{ + gdouble xres, yres; + + gimp_size_entry_set_unit (private->resolution_entry, + gimp_get_default_unit ()); + + gimp_image_get_resolution (private->image, &xres, &yres); + print_size_dialog_set_resolution (private, xres, yres); +} + +static void +print_size_dialog_size_changed (GtkWidget *widget, + PrintSizeDialog *private) +{ + GimpImage *image = private->image; + gdouble width; + gdouble height; + gdouble xres; + gdouble yres; + gdouble scale; + + scale = gimp_unit_get_factor (gimp_size_entry_get_unit (private->size_entry)); + + width = gimp_size_entry_get_value (private->size_entry, 0); + height = gimp_size_entry_get_value (private->size_entry, 1); + + xres = scale * gimp_image_get_width (image) / MAX (0.001, width); + yres = scale * gimp_image_get_height (image) / MAX (0.001, height); + + xres = CLAMP (xres, GIMP_MIN_RESOLUTION, GIMP_MAX_RESOLUTION); + yres = CLAMP (yres, GIMP_MIN_RESOLUTION, GIMP_MAX_RESOLUTION); + + print_size_dialog_set_resolution (private, xres, yres); + print_size_dialog_set_size (private, + gimp_image_get_width (image), + gimp_image_get_height (image)); +} + +static void +print_size_dialog_resolution_changed (GtkWidget *widget, + PrintSizeDialog *private) +{ + GimpSizeEntry *entry = private->resolution_entry; + gdouble xres = gimp_size_entry_get_refval (entry, 0); + gdouble yres = gimp_size_entry_get_refval (entry, 1); + + print_size_dialog_set_resolution (private, xres, yres); +} + +static void +print_size_dialog_set_size (PrintSizeDialog *private, + gdouble width, + gdouble height) +{ + g_signal_handlers_block_by_func (private->size_entry, + print_size_dialog_size_changed, + private); + + gimp_size_entry_set_refval (private->size_entry, 0, width); + gimp_size_entry_set_refval (private->size_entry, 1, height); + + g_signal_handlers_unblock_by_func (private->size_entry, + print_size_dialog_size_changed, + private); +} + +static void +print_size_dialog_set_resolution (PrintSizeDialog *private, + gdouble xres, + gdouble yres) +{ + if (private->chain && gimp_chain_button_get_active (private->chain)) + { + if (xres != private->xres) + yres = xres; + else + xres = yres; + } + + private->xres = xres; + private->yres = yres; + + g_signal_handlers_block_by_func (private->resolution_entry, + print_size_dialog_resolution_changed, + private); + + gimp_size_entry_set_refval (private->resolution_entry, 0, xres); + gimp_size_entry_set_refval (private->resolution_entry, 1, yres); + + g_signal_handlers_unblock_by_func (private->resolution_entry, + print_size_dialog_resolution_changed, + private); + + g_signal_handlers_block_by_func (private->size_entry, + print_size_dialog_size_changed, + private); + + gimp_size_entry_set_resolution (private->size_entry, 0, xres, TRUE); + gimp_size_entry_set_resolution (private->size_entry, 1, yres, TRUE); + + g_signal_handlers_unblock_by_func (private->size_entry, + print_size_dialog_size_changed, + private); +} |