print-size-dialog.c 15.8 KB
Newer Older
1
/* GIMP - The GNU Image Manipulation Program
2 3
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
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 8 9 10 11 12 13 14
 * (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
15
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 17 18 19
 */

#include "config.h"

20
#include <gegl.h>
21 22
#include <gtk/gtk.h>

23
#include "libgimpbase/gimpbase.h"
24 25 26 27
#include "libgimpwidgets/gimpwidgets.h"

#include "dialogs-types.h"

28
#include "core/gimpcontext.h"
29
#include "core/gimpimage.h"
30
#include "core/gimp-utils.h"
31 32 33 34 35 36 37 38 39 40

#include "widgets/gimphelp-ids.h"
#include "widgets/gimpviewabledialog.h"

#include "print-size-dialog.h"

#include "gimp-intl.h"


#define RESPONSE_RESET 1
41
#define SB_WIDTH       8
42 43


44 45 46
typedef struct _PrintSizeDialog PrintSizeDialog;

struct _PrintSizeDialog
47 48
{
  GimpImage              *image;
49 50 51 52 53
  GimpSizeEntry          *size_entry;
  GimpSizeEntry          *resolution_entry;
  GimpChainButton        *chain;
  gdouble                 xres;
  gdouble                 yres;
54 55
  GimpResolutionCallback  callback;
  gpointer                user_data;
56 57
};

58

59
/*  local function prototypes  */
60

61 62 63 64 65
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);
66

67 68 69 70
static void   print_size_dialog_size_changed       (GtkWidget       *widget,
                                                    PrintSizeDialog *private);
static void   print_size_dialog_resolution_changed (GtkWidget       *widget,
                                                    PrintSizeDialog *private);
71 72 73 74 75 76
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);
77

78

79 80
/*  public functions  */

81 82
GtkWidget *
print_size_dialog_new (GimpImage              *image,
83
                       GimpContext            *context,
84 85 86 87 88 89 90 91
                       const gchar            *title,
                       const gchar            *role,
                       GtkWidget              *parent,
                       GimpHelpFunc            help_func,
                       const gchar            *help_id,
                       GimpResolutionCallback  callback,
                       gpointer                user_data)
{
92
  PrintSizeDialog *private;
93 94
  GtkWidget       *dialog;
  GtkWidget       *frame;
Simon Budig's avatar
Simon Budig committed
95
  GtkWidget       *grid;
96 97 98 99 100 101
  GtkWidget       *entry;
  GtkWidget       *label;
  GtkWidget       *width;
  GtkWidget       *height;
  GtkWidget       *hbox;
  GtkWidget       *chain;
102
  GtkAdjustment   *adj;
103
  GList           *focus_chain = NULL;
104 105

  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
106
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
107 108
  g_return_val_if_fail (callback != NULL, NULL);

109 110 111 112 113 114 115 116
  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);

117
  dialog = gimp_viewable_dialog_new (GIMP_VIEWABLE (image), context,
118
                                     title, role,
119
                                     GIMP_ICON_DOCUMENT_PRINT_RESOLUTION, title,
120 121 122
                                     parent,
                                     help_func, help_id,

123 124 125
                                     _("_Reset"),  RESPONSE_RESET,
                                     _("_Cancel"), GTK_RESPONSE_CANCEL,
                                     _("_OK"),     GTK_RESPONSE_OK,
126 127 128

                                     NULL);

129
  gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
130 131 132 133
                                           RESPONSE_RESET,
                                           GTK_RESPONSE_OK,
                                           GTK_RESPONSE_CANCEL,
                                           -1);
134

135
  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
136

137 138
  g_object_weak_ref (G_OBJECT (dialog),
                     (GWeakNotify) print_size_dialog_free, private);
139

140 141 142 143
  g_signal_connect (dialog, "response",
                    G_CALLBACK (print_size_dialog_response),
                    private);

144
  frame = gimp_frame_new (_("Print Size"));
145
  gtk_container_set_border_width (GTK_CONTAINER (frame), 12);
146
  gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
147
                      frame, FALSE, FALSE, 0);
148 149
  gtk_widget_show (frame);

Simon Budig's avatar
Simon Budig committed
150 151 152 153
  grid = gtk_grid_new ();
  gtk_grid_set_row_spacing (GTK_GRID (grid), 12);
  gtk_container_add (GTK_CONTAINER (frame), grid);
  gtk_widget_show (grid);
154 155 156

  /*  the print size entry  */

157 158 159
  adj = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0);
  width = gtk_spin_button_new (adj, 1.0, 2);
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (width), TRUE);
160 161
  gtk_entry_set_width_chars (GTK_ENTRY (width), SB_WIDTH);

162 163 164
  adj = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0);
  height = gtk_spin_button_new (adj, 1.0, 2);
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (height), TRUE);
165 166
  gtk_entry_set_width_chars (GTK_ENTRY (height), SB_WIDTH);

167
  entry = gimp_size_entry_new (0, gimp_get_default_unit (), "%p",
168 169
                               FALSE, FALSE, FALSE, SB_WIDTH,
                               GIMP_SIZE_ENTRY_UPDATE_SIZE);
170
  private->size_entry = GIMP_SIZE_ENTRY (entry);
171 172

  label = gtk_label_new_with_mnemonic (_("_Width:"));
173
  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
174
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), width);
Simon Budig's avatar
Simon Budig committed
175
  gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
176 177 178
  gtk_widget_show (label);

  label = gtk_label_new_with_mnemonic (_("H_eight:"));
179
  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
180
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), height);
Simon Budig's avatar
Simon Budig committed
181
  gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
182 183
  gtk_widget_show (label);

Michael Natterer's avatar
Michael Natterer committed
184
  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
Simon Budig's avatar
Simon Budig committed
185
  gtk_grid_attach (GTK_GRID (grid), hbox, 1, 0, 1, 2);
186 187 188 189 190 191
  gtk_widget_show (hbox);

  gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
  gtk_widget_show (entry);

  gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry),
192
                             GTK_SPIN_BUTTON (height), NULL);
193
  gtk_grid_attach (GTK_GRID (entry), height, 0, 1, 1, 1);
194 195 196
  gtk_widget_show (height);

  gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry),
197
                             GTK_SPIN_BUTTON (width), NULL);
198
  gtk_grid_attach (GTK_GRID (entry), width, 0, 0, 1, 1);
199 200
  gtk_widget_show (width);

201 202 203 204 205 206 207 208 209
  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);
210

211 212 213 214
  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));
215 216 217

  /*  the resolution entry  */

218 219 220
  adj = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0);
  width = gtk_spin_button_new (adj, 1.0, 2);
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (width), TRUE);
221 222
  gtk_entry_set_width_chars (GTK_ENTRY (width), SB_WIDTH);

223 224 225
  adj = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0);
  height = gtk_spin_button_new (adj, 1.0, 2);
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (height), TRUE);
226 227 228
  gtk_entry_set_width_chars (GTK_ENTRY (height), SB_WIDTH);

  label = gtk_label_new_with_mnemonic (_("_X resolution:"));
229
  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
230
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), width);
Simon Budig's avatar
Simon Budig committed
231
  gtk_grid_attach (GTK_GRID (grid), label, 0, 2, 1, 1);
232 233 234
  gtk_widget_show (label);

  label = gtk_label_new_with_mnemonic (_("_Y resolution:"));
235
  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
236
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), height);
Simon Budig's avatar
Simon Budig committed
237
  gtk_grid_attach (GTK_GRID (grid), label, 0, 3, 1, 1);
238 239
  gtk_widget_show (label);

Michael Natterer's avatar
Michael Natterer committed
240
  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
Simon Budig's avatar
Simon Budig committed
241
  gtk_grid_attach (GTK_GRID (grid), hbox, 1, 2, 1, 2);
242 243 244 245 246
  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);
247
  private->resolution_entry = GIMP_SIZE_ENTRY (entry);
248 249 250 251 252 253

  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);
254
  gtk_grid_attach (GTK_GRID (entry), height, 0, 1, 1, 1);
255 256 257 258
  gtk_widget_show (height);

  gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry),
                             GTK_SPIN_BUTTON (width), NULL);
259
  gtk_grid_attach (GTK_GRID (entry), width, 0, 0, 1, 1);
260 261 262 263 264 265 266 267 268
  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);

269 270
  gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (entry), 0, private->xres);
  gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (entry), 1, private->yres);
271 272

  chain = gimp_chain_button_new (GIMP_CHAIN_RIGHT);
273 274
  if (ABS (private->xres - private->yres) < GIMP_MIN_RESOLUTION)
    gimp_chain_button_set_active (GIMP_CHAIN_BUTTON (chain), TRUE);
275
  gtk_grid_attach (GTK_GRID (entry), chain, 1, 0, 1, 2);
276
  gtk_widget_show (chain);
277

278 279
  private->chain = GIMP_CHAIN_BUTTON (chain);

280 281 282 283 284 285 286 287
  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);

288
  g_signal_connect (private->size_entry, "value-changed",
289 290
                    G_CALLBACK (print_size_dialog_size_changed),
                    private);
291
  g_signal_connect (private->resolution_entry, "value-changed",
292 293
                    G_CALLBACK (print_size_dialog_resolution_changed),
                    private);
294

295 296 297
  return dialog;
}

298 299 300 301 302 303 304 305 306

/*  private functions  */

static void
print_size_dialog_free (PrintSizeDialog *private)
{
  g_slice_free (PrintSizeDialog, private);
}

307 308 309 310 311
static void
print_size_dialog_response (GtkWidget       *dialog,
                            gint             response_id,
                            PrintSizeDialog *private)
{
312
  GimpSizeEntry *entry = private->resolution_entry;
313 314 315 316 317 318 319 320 321 322

  switch (response_id)
    {
    case RESPONSE_RESET:
      print_size_dialog_reset (private);
      break;

    case GTK_RESPONSE_OK:
      private->callback (dialog,
                         private->image,
323 324
                         gimp_size_entry_get_refval (entry, 0),
                         gimp_size_entry_get_refval (entry, 1),
325
                         gimp_size_entry_get_unit (entry),
326 327 328 329 330 331 332 333 334 335 336 337 338 339
                         private->user_data);
      break;

    default:
      gtk_widget_destroy (dialog);
      break;
    }
}

static void
print_size_dialog_reset (PrintSizeDialog *private)
{
  gdouble  xres, yres;

340
  gimp_size_entry_set_unit (private->resolution_entry,
341
                            gimp_get_default_unit ());
342

343
  gimp_image_get_resolution (private->image, &xres, &yres);
344 345 346 347 348 349 350 351 352 353 354 355
  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;
356 357 358
  gdouble    scale;

  scale = gimp_unit_get_factor (gimp_size_entry_get_unit (private->size_entry));
359

360 361
  width  = gimp_size_entry_get_value (private->size_entry, 0);
  height = gimp_size_entry_get_value (private->size_entry, 1);
362

363 364
  xres = scale * gimp_image_get_width  (image) / MAX (0.001, width);
  yres = scale * gimp_image_get_height (image) / MAX (0.001, height);
365 366 367 368 369

  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);
370 371 372
  print_size_dialog_set_size (private,
                              gimp_image_get_width  (image),
                              gimp_image_get_height (image));
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
}

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)
411
        yres = xres;
412
      else
413
        xres = yres;
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
    }

  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);
440
}