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 <gegl.h>
21 #include <gtk/gtk.h>
22 
23 #include "libgimpwidgets/gimpwidgets.h"
24 
25 #include "dialogs-types.h"
26 
27 #include "core/gimpcontext.h"
28 #include "core/gimpimage.h"
29 #include "core/gimpitem.h"
30 
31 #include "widgets/gimphelp-ids.h"
32 #include "widgets/gimpmessagebox.h"
33 #include "widgets/gimpsizebox.h"
34 #include "widgets/gimpviewabledialog.h"
35 
36 #include "scale-dialog.h"
37 
38 #include "gimp-intl.h"
39 
40 
41 #define RESPONSE_RESET 1
42 
43 typedef struct _ScaleDialog ScaleDialog;
44 
45 struct _ScaleDialog
46 {
47   GimpViewable          *viewable;
48   GimpUnit               unit;
49   GimpInterpolationType  interpolation;
50   GtkWidget             *box;
51   GtkWidget             *combo;
52   GimpScaleCallback      callback;
53   gpointer               user_data;
54 };
55 
56 
57 /*  local function prototypes  */
58 
59 static void   scale_dialog_free     (ScaleDialog *private);
60 static void   scale_dialog_response (GtkWidget   *dialog,
61                                      gint         response_id,
62                                      ScaleDialog *private);
63 static void   scale_dialog_reset    (ScaleDialog *private);
64 
65 
66 /*  public function  */
67 
68 GtkWidget *
scale_dialog_new(GimpViewable * viewable,GimpContext * context,const gchar * title,const gchar * role,GtkWidget * parent,GimpHelpFunc help_func,const gchar * help_id,GimpUnit unit,GimpInterpolationType interpolation,GimpScaleCallback callback,gpointer user_data)69 scale_dialog_new (GimpViewable          *viewable,
70                   GimpContext           *context,
71                   const gchar           *title,
72                   const gchar           *role,
73                   GtkWidget             *parent,
74                   GimpHelpFunc           help_func,
75                   const gchar           *help_id,
76                   GimpUnit               unit,
77                   GimpInterpolationType  interpolation,
78                   GimpScaleCallback      callback,
79                   gpointer               user_data)
80 {
81   GtkWidget   *dialog;
82   GtkWidget   *vbox;
83   GtkWidget   *hbox;
84   GtkWidget   *frame;
85   GtkWidget   *label;
86   ScaleDialog *private;
87   GimpImage   *image = NULL;
88   const gchar *text  = NULL;
89   gint         width, height;
90   gdouble      xres, yres;
91 
92   g_return_val_if_fail (GIMP_IS_VIEWABLE (viewable), NULL);
93   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
94   g_return_val_if_fail (callback != NULL, NULL);
95 
96   if (GIMP_IS_IMAGE (viewable))
97     {
98       image = GIMP_IMAGE (viewable);
99 
100       width  = gimp_image_get_width (image);
101       height = gimp_image_get_height (image);
102 
103       text = _("Image Size");
104     }
105   else if (GIMP_IS_ITEM (viewable))
106     {
107       GimpItem *item = GIMP_ITEM (viewable);
108 
109       image = gimp_item_get_image (item);
110 
111       width  = gimp_item_get_width  (item);
112       height = gimp_item_get_height (item);
113 
114       text = _("Layer Size");
115     }
116   else
117     {
118       g_return_val_if_reached (NULL);
119     }
120 
121   private = g_slice_new0 (ScaleDialog);
122 
123   private->viewable      = viewable;
124   private->interpolation = interpolation;
125   private->unit          = unit;
126   private->callback      = callback;
127   private->user_data     = user_data;
128 
129   gimp_image_get_resolution (image, &xres, &yres);
130 
131   dialog = gimp_viewable_dialog_new (viewable, context,
132                                      title, role, GIMP_ICON_OBJECT_SCALE, title,
133                                      parent,
134                                      help_func, help_id,
135 
136                                      _("_Reset"),  RESPONSE_RESET,
137                                      _("_Cancel"), GTK_RESPONSE_CANCEL,
138                                      _("_Scale"),  GTK_RESPONSE_OK,
139 
140                                      NULL);
141 
142   gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
143                                            RESPONSE_RESET,
144                                            GTK_RESPONSE_OK,
145                                            GTK_RESPONSE_CANCEL,
146                                            -1);
147 
148   gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
149 
150   g_object_weak_ref (G_OBJECT (dialog),
151                      (GWeakNotify) scale_dialog_free, private);
152 
153   g_signal_connect (dialog, "response",
154                     G_CALLBACK (scale_dialog_response),
155                     private);
156 
157   private->box = g_object_new (GIMP_TYPE_SIZE_BOX,
158                                "width",           width,
159                                "height",          height,
160                                "unit",            unit,
161                                "xresolution",     xres,
162                                "yresolution",     yres,
163                                "resolution-unit", gimp_image_get_unit (image),
164                                "keep-aspect",     TRUE,
165                                "edit-resolution", GIMP_IS_IMAGE (viewable),
166                                NULL);
167 
168   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
169   gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
170   gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
171                       vbox, TRUE, TRUE, 0);
172   gtk_widget_show (vbox);
173 
174   frame = gimp_frame_new (text);
175   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
176   gtk_widget_show (frame);
177 
178   gtk_container_add (GTK_CONTAINER (frame), private->box);
179   gtk_widget_show (private->box);
180 
181   frame = gimp_frame_new (_("Quality"));
182   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
183   gtk_widget_show (frame);
184 
185   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
186   gtk_container_add (GTK_CONTAINER (frame), vbox);
187   gtk_widget_show (vbox);
188 
189   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
190   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
191   gtk_widget_show (hbox);
192 
193   label = gtk_label_new_with_mnemonic (_("I_nterpolation:"));
194   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
195   gtk_widget_show (label);
196 
197   gtk_size_group_add_widget (GIMP_SIZE_BOX (private->box)->size_group, label);
198 
199   private->combo = gimp_enum_combo_box_new (GIMP_TYPE_INTERPOLATION_TYPE);
200   gtk_label_set_mnemonic_widget (GTK_LABEL (label), private->combo);
201   gtk_box_pack_start (GTK_BOX (hbox), private->combo, TRUE, TRUE, 0);
202   gtk_widget_show (private->combo);
203 
204   gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (private->combo),
205                                  private->interpolation);
206 
207   return dialog;
208 }
209 
210 
211 /*  private functions  */
212 
213 static void
scale_dialog_free(ScaleDialog * private)214 scale_dialog_free (ScaleDialog *private)
215 {
216   g_slice_free (ScaleDialog, private);
217 }
218 
219 static void
scale_dialog_response(GtkWidget * dialog,gint response_id,ScaleDialog * private)220 scale_dialog_response (GtkWidget   *dialog,
221                        gint         response_id,
222                        ScaleDialog *private)
223 {
224   GimpUnit  unit          = private->unit;
225   gint      interpolation = private->interpolation;
226   GimpUnit  resolution_unit;
227   gint      width, height;
228   gdouble   xres, yres;
229 
230   switch (response_id)
231     {
232     case RESPONSE_RESET:
233       scale_dialog_reset (private);
234       break;
235 
236     case GTK_RESPONSE_OK:
237       g_object_get (private->box,
238                     "width",           &width,
239                     "height",          &height,
240                     "unit",            &unit,
241                     "xresolution",     &xres,
242                     "yresolution",     &yres,
243                     "resolution-unit", &resolution_unit,
244                     NULL);
245 
246       gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (private->combo),
247                                      &interpolation);
248 
249       private->callback (dialog,
250                          private->viewable,
251                          width, height, unit, interpolation,
252                          xres, yres, resolution_unit,
253                          private->user_data);
254       break;
255 
256     default:
257       gtk_widget_destroy (dialog);
258       break;
259     }
260 }
261 
262 static void
scale_dialog_reset(ScaleDialog * private)263 scale_dialog_reset (ScaleDialog *private)
264 {
265   GimpImage *image;
266   gint       width, height;
267   gdouble    xres, yres;
268 
269   if (GIMP_IS_IMAGE (private->viewable))
270     {
271       image = GIMP_IMAGE (private->viewable);
272 
273       width  = gimp_image_get_width (image);
274       height = gimp_image_get_height (image);
275     }
276   else if (GIMP_IS_ITEM (private->viewable))
277     {
278       GimpItem *item = GIMP_ITEM (private->viewable);
279 
280       image = gimp_item_get_image (item);
281 
282       width  = gimp_item_get_width  (item);
283       height = gimp_item_get_height (item);
284     }
285   else
286     {
287       g_return_if_reached ();
288     }
289 
290   gimp_image_get_resolution (image, &xres, &yres);
291 
292   g_object_set (private->box,
293                 "keep-aspect",     FALSE,
294                 NULL);
295 
296   g_object_set (private->box,
297                 "width",           width,
298                 "height",          height,
299                 "unit",            private->unit,
300                 NULL);
301 
302   g_object_set (private->box,
303                 "keep-aspect",     TRUE,
304                 "xresolution",     xres,
305                 "yresolution",     yres,
306                 "resolution-unit", gimp_image_get_unit (image),
307                 NULL);
308 
309   gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (private->combo),
310                                  private->interpolation);
311 }
312