1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include <string.h>
21 
22 #include <gegl.h>
23 #include <gtk/gtk.h>
24 
25 #include "libgimpbase/gimpbase.h"
26 #include "libgimpwidgets/gimpwidgets.h"
27 
28 #include "dialogs-types.h"
29 
30 #include "config/gimpguiconfig.h"
31 
32 #include "core/gimp.h"
33 #include "core/gimpcontext.h"
34 #include "core/gimpimage.h"
35 #include "core/gimpimage-scale.h"
36 
37 #include "widgets/gimphelp-ids.h"
38 #include "widgets/gimpmessagebox.h"
39 #include "widgets/gimpmessagedialog.h"
40 
41 #include "scale-dialog.h"
42 
43 #include "image-scale-dialog.h"
44 
45 #include "gimp-intl.h"
46 
47 
48 typedef struct
49 {
50   GtkWidget             *dialog;
51 
52   GimpImage             *image;
53 
54   gint                   width;
55   gint                   height;
56   GimpUnit               unit;
57   GimpInterpolationType  interpolation;
58   gdouble                xresolution;
59   gdouble                yresolution;
60   GimpUnit               resolution_unit;
61 
62   GimpScaleCallback      callback;
63   gpointer               user_data;
64 } ImageScaleDialog;
65 
66 
67 /*  local function prototypes  */
68 
69 static void        image_scale_dialog_free      (ImageScaleDialog      *private);
70 static void        image_scale_callback         (GtkWidget             *widget,
71                                                  GimpViewable          *viewable,
72                                                  gint                   width,
73                                                  gint                   height,
74                                                  GimpUnit               unit,
75                                                  GimpInterpolationType  interpolation,
76                                                  gdouble                xresolution,
77                                                  gdouble                yresolution,
78                                                  GimpUnit               resolution_unit,
79                                                  gpointer               data);
80 
81 static GtkWidget * image_scale_confirm_dialog   (ImageScaleDialog      *private);
82 static void        image_scale_confirm_large    (ImageScaleDialog      *private,
83                                                  gint64                 new_memsize,
84                                                  gint64                 max_memsize);
85 static void        image_scale_confirm_small    (ImageScaleDialog      *private);
86 static void        image_scale_confirm_response (GtkWidget             *widget,
87                                                  gint                   response_id,
88                                                  ImageScaleDialog      *private);
89 
90 
91 /*  public functions  */
92 
93 GtkWidget *
image_scale_dialog_new(GimpImage * image,GimpContext * context,GtkWidget * parent,GimpUnit unit,GimpInterpolationType interpolation,GimpScaleCallback callback,gpointer user_data)94 image_scale_dialog_new (GimpImage             *image,
95                         GimpContext           *context,
96                         GtkWidget             *parent,
97                         GimpUnit               unit,
98                         GimpInterpolationType  interpolation,
99                         GimpScaleCallback      callback,
100                         gpointer               user_data)
101 {
102   ImageScaleDialog *private;
103 
104   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
105   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
106   g_return_val_if_fail (callback != NULL, NULL);
107 
108   private = g_slice_new0 (ImageScaleDialog);
109 
110   private->image     = image;
111   private->callback  = callback;
112   private->user_data = user_data;
113 
114   private->dialog = scale_dialog_new (GIMP_VIEWABLE (image), context,
115                                       C_("dialog-title", "Scale Image"),
116                                       "gimp-image-scale",
117                                       parent,
118                                       gimp_standard_help_func,
119                                       GIMP_HELP_IMAGE_SCALE,
120                                       unit,
121                                       interpolation,
122                                       image_scale_callback,
123                                       private);
124 
125   g_object_weak_ref (G_OBJECT (private->dialog),
126                      (GWeakNotify) image_scale_dialog_free, private);
127 
128   return private->dialog;
129 }
130 
131 
132 /*  private functions  */
133 
134 static void
image_scale_dialog_free(ImageScaleDialog * private)135 image_scale_dialog_free (ImageScaleDialog *private)
136 {
137   g_slice_free (ImageScaleDialog, private);
138 }
139 
140 static void
image_scale_callback(GtkWidget * widget,GimpViewable * viewable,gint width,gint height,GimpUnit unit,GimpInterpolationType interpolation,gdouble xresolution,gdouble yresolution,GimpUnit resolution_unit,gpointer data)141 image_scale_callback (GtkWidget             *widget,
142                       GimpViewable          *viewable,
143                       gint                   width,
144                       gint                   height,
145                       GimpUnit               unit,
146                       GimpInterpolationType  interpolation,
147                       gdouble                xresolution,
148                       gdouble                yresolution,
149                       GimpUnit               resolution_unit,
150                       gpointer               data)
151 {
152   ImageScaleDialog        *private = data;
153   GimpImage               *image   = GIMP_IMAGE (viewable);
154   GimpImageScaleCheckType  scale_check;
155   gint64                   max_memsize;
156   gint64                   new_memsize;
157 
158   private->width           = width;
159   private->height          = height;
160   private->unit            = unit;
161   private->interpolation   = interpolation;
162   private->xresolution     = xresolution;
163   private->yresolution     = yresolution;
164   private->resolution_unit = resolution_unit;
165 
166   gtk_widget_set_sensitive (widget, FALSE);
167 
168   max_memsize = GIMP_GUI_CONFIG (image->gimp->config)->max_new_image_size;
169 
170   scale_check = gimp_image_scale_check (image,
171                                         width, height, max_memsize,
172                                         &new_memsize);
173   switch (scale_check)
174     {
175     case GIMP_IMAGE_SCALE_TOO_BIG:
176       image_scale_confirm_large (private, new_memsize, max_memsize);
177       break;
178 
179     case GIMP_IMAGE_SCALE_TOO_SMALL:
180       image_scale_confirm_small (private);
181       break;
182 
183     case GIMP_IMAGE_SCALE_OK:
184       private->callback (private->dialog,
185                          GIMP_VIEWABLE (private->image),
186                          private->width,
187                          private->height,
188                          private->unit,
189                          private->interpolation,
190                          private->xresolution,
191                          private->yresolution,
192                          private->resolution_unit,
193                          private->user_data);
194       break;
195     }
196 }
197 
198 static GtkWidget *
image_scale_confirm_dialog(ImageScaleDialog * private)199 image_scale_confirm_dialog (ImageScaleDialog *private)
200 {
201   GtkWidget *widget;
202 
203   widget = gimp_message_dialog_new (_("Confirm Scaling"),
204                                     GIMP_ICON_DIALOG_WARNING,
205                                     private->dialog,
206                                     GTK_DIALOG_DESTROY_WITH_PARENT,
207                                     gimp_standard_help_func,
208                                     GIMP_HELP_IMAGE_SCALE_WARNING,
209 
210                                     _("_Cancel"), GTK_RESPONSE_CANCEL,
211                                     _("_Scale"),  GTK_RESPONSE_OK,
212 
213                                     NULL);
214 
215   gtk_dialog_set_alternative_button_order (GTK_DIALOG (widget),
216                                            GTK_RESPONSE_OK,
217                                            GTK_RESPONSE_CANCEL,
218                                            -1);
219 
220   g_signal_connect (widget, "response",
221                     G_CALLBACK (image_scale_confirm_response),
222                     private);
223 
224   return widget;
225 }
226 
227 static void
image_scale_confirm_large(ImageScaleDialog * private,gint64 new_memsize,gint64 max_memsize)228 image_scale_confirm_large (ImageScaleDialog *private,
229                            gint64            new_memsize,
230                            gint64            max_memsize)
231 {
232   GtkWidget *widget = image_scale_confirm_dialog (private);
233   gchar     *size;
234 
235   size = g_format_size (new_memsize);
236   gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (widget)->box,
237                                      _("You are trying to create an image "
238                                        "with a size of %s."), size);
239   g_free (size);
240 
241   size = g_format_size (max_memsize);
242   gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (widget)->box,
243                              _("Scaling the image to the chosen size will "
244                                "make it use more memory than what is "
245                                "configured as \"Maximum Image Size\" in the "
246                                "Preferences dialog (currently %s)."), size);
247   g_free (size);
248 
249   gtk_widget_show (widget);
250 }
251 
252 static void
image_scale_confirm_small(ImageScaleDialog * private)253 image_scale_confirm_small (ImageScaleDialog *private)
254 {
255   GtkWidget *widget = image_scale_confirm_dialog (private);
256 
257   gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (widget)->box,
258                                      _("Scaling the image to the chosen size "
259                                        "will shrink some layers completely "
260                                        "away."));
261   gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (widget)->box,
262                              _("Is this what you want to do?"));
263 
264   gtk_widget_show (widget);
265 }
266 
267 static void
image_scale_confirm_response(GtkWidget * widget,gint response_id,ImageScaleDialog * private)268 image_scale_confirm_response (GtkWidget        *widget,
269                               gint              response_id,
270                               ImageScaleDialog *private)
271 {
272   gtk_widget_destroy (widget);
273 
274   if (response_id == GTK_RESPONSE_OK)
275     {
276       private->callback (private->dialog,
277                          GIMP_VIEWABLE (private->image),
278                          private->width,
279                          private->height,
280                          private->unit,
281                          private->interpolation,
282                          private->xresolution,
283                          private->yresolution,
284                          private->resolution_unit,
285                          private->user_data);
286     }
287   else
288     {
289       gtk_widget_set_sensitive (private->dialog, TRUE);
290     }
291 }
292