print-page-layout.c 32.3 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 <https://www.gnu.org/licenses/>.
16 17 18 19
 */

#include "config.h"

20 21
#include <string.h>

22 23 24 25 26
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>

#include "print.h"
#include "print-page-layout.h"
27
#include "print-preview.h"
28 29 30

#include "libgimp/stdplugins-intl.h"

Sven Neumann's avatar
Sven Neumann committed
31

32 33
typedef struct
{
Sven Neumann's avatar
Sven Neumann committed
34
  PrintData       *data;
35 36
  gint             image_width;
  gint             image_height;
Sven Neumann's avatar
Sven Neumann committed
37 38 39
  GimpSizeEntry   *size_entry;
  GimpSizeEntry   *resolution_entry;
  GimpChainButton *chain;
40
  GtkWidget       *center_combo;
41
  GtkWidget       *area_label;
42
  GtkWidget       *preview;
43 44 45 46
  GtkAdjustment   *left_adj;
  GtkAdjustment   *right_adj;
  GtkAdjustment   *top_adj;
  GtkAdjustment   *bottom_adj;
47 48
} PrintSizeInfo;

49 50 51 52 53 54 55 56 57 58
enum
{
  BOTTOM,
  TOP,
  RIGHT,
  LEFT,
  WIDTH,
  HEIGHT
};

59

60
static void        print_page_setup_notify            (GtkPrintOperation *operation);
61 62 63 64
static void        update_custom_widget               (GtkPrintOperation *operation,
                                                       GtkWidget         *custom_widget,
                                                       GtkPageSetup      *page_setup,
                                                       GtkPrintSettings  *print_settings);
65

66
static GtkWidget * print_size_frame                   (PrintData    *data,
67 68
                                                       GtkSizeGroup *label_group,
                                                       GtkSizeGroup *entry_group);
69
static GtkWidget * print_offset_frame                 (PrintData    *data,
70 71
                                                       GtkSizeGroup *label_group,
                                                       GtkSizeGroup *entry_group);
72

73
static void        print_size_info_update_offsets     (void);
74
static void        print_size_info_size_changed       (GtkWidget     *widget);
75 76
static void        print_size_info_offset_max_changed (GtkAdjustment *adj,
                                                       gpointer       data);
77
static void        print_size_info_resolution_changed (GtkWidget     *widget);
78
static void        print_size_info_unit_changed       (GtkWidget     *widget);
79 80 81 82
static void        print_size_info_preview_offset_changed
                                                      (GtkWidget     *widget,
                                                       gdouble        offset_x,
                                                       gdouble        offset_y);
83 84
static void        print_size_info_center_changed     (GtkWidget     *widget);
static void        print_size_info_center_none        (void);
85 86
static void        print_size_info_use_full_page_toggled
                                                      (GtkWidget     *widget);
87 88 89 90 91

static void        print_size_info_set_resolution     (PrintSizeInfo *info,
                                                       gdouble        xres,
                                                       gdouble        yres);

92

93
static void        print_size_info_set_page_setup     (PrintSizeInfo *info);
94

95 96
static void        print_draw_crop_marks_toggled      (GtkWidget     *widget);

97
static void        print_resolution_load_defaults     (PrintSizeInfo *info);
98 99

static PrintSizeInfo  info;
100 101 102


GtkWidget *
103 104
print_page_layout_gui (PrintData   *data,
                       const gchar *help_id)
105
{
106
  GtkWidget    *main_hbox;
107
  GtkWidget    *main_vbox;
108 109 110
  GtkWidget    *button;
  GtkWidget    *frame;
  GtkPageSetup *setup;
111 112
  GtkSizeGroup *label_group;
  GtkSizeGroup *entry_group;
113

114 115 116
  memset (&info, 0, sizeof (PrintSizeInfo));

  info.data         = data;
117 118
  info.image_width  = gimp_drawable_width (data->drawable_id);
  info.image_height = gimp_drawable_height (data->drawable_id);
119

120 121 122 123 124 125 126
  setup = gtk_print_operation_get_default_page_setup (data->operation);
  if (! setup)
    {
      setup = gtk_page_setup_new ();
      gtk_print_operation_set_default_page_setup (data->operation, setup);
    }

127
  /*  main hbox  */
128
  main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
129
  gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
130 131

  /*  main vbox  */
132
  main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
133 134 135
  gtk_box_pack_start (GTK_BOX (main_hbox), main_vbox, FALSE, FALSE, 0);
  gtk_widget_show (main_vbox);

136 137 138
  label_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
  entry_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);

139
  /* size entry area for the image's print size */
140

141
  frame = print_size_frame (data, label_group, entry_group);
Simon Budig's avatar
Simon Budig committed
142 143
  gtk_widget_set_vexpand (frame, FALSE);
  gtk_widget_set_valign (frame, GTK_ALIGN_START);
144
  gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
145 146 147 148
  gtk_widget_show (frame);

  /* offset entry area for the image's offset position */

149
  frame = print_offset_frame (data, label_group, entry_group);
Simon Budig's avatar
Simon Budig committed
150 151
  gtk_widget_set_vexpand (frame, FALSE);
  gtk_widget_set_valign (frame, GTK_ALIGN_START);
152
  gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
153
  gtk_widget_show (frame);
Sven Neumann's avatar
Sven Neumann committed
154

155 156 157
  g_object_unref (label_group);
  g_object_unref (entry_group);

158
  button = gtk_check_button_new_with_mnemonic (_("Ignore Page _Margins"));
159

160 161
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
                                data->use_full_page);
162
  gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0);
163 164 165 166 167
  g_signal_connect (button, "toggled",
                    G_CALLBACK (print_size_info_use_full_page_toggled),
                    NULL);
  gtk_widget_show (button);

168 169 170 171 172 173 174 175 176 177 178
  /* crop marks toggle */
  button = gtk_check_button_new_with_mnemonic (_("_Draw Crop Marks"));

  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
                                data->draw_crop_marks);
  gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0);
  g_signal_connect (button, "toggled",
                    G_CALLBACK (print_draw_crop_marks_toggled),
                    NULL);
  gtk_widget_show (button);

179 180 181 182 183 184 185 186 187
  /* preview */
  frame = gimp_frame_new (_("Preview"));
  gtk_box_pack_start (GTK_BOX (main_hbox), frame, TRUE, TRUE, 0);
  gtk_widget_show (frame);

  info.preview = print_preview_new (setup, data->drawable_id);
  print_preview_set_use_full_page (PRINT_PREVIEW (info.preview),
                                   data->use_full_page);
  gtk_container_add (GTK_CONTAINER (frame), info.preview);
188 189 190 191 192 193
  gtk_widget_show (info.preview);

  g_signal_connect (info.preview, "offsets-changed",
                    G_CALLBACK (print_size_info_preview_offset_changed),
                    NULL);

194 195
  print_size_info_set_page_setup (&info);

196 197
  g_signal_connect_object (data->operation, "notify::default-page-setup",
                           G_CALLBACK (print_page_setup_notify),
198
                           main_hbox, 0);
199 200 201
  g_signal_connect_object (data->operation, "update-custom-widget",
                           G_CALLBACK (update_custom_widget),
                           main_hbox, 0);
202

203 204
  gimp_help_connect (main_hbox, gimp_standard_help_func, help_id, NULL);

205
  return main_hbox;
206 207 208
}

static void
209
print_page_setup_notify (GtkPrintOperation *operation)
210
{
211
  GtkPageSetup *setup;
212

213
  setup = gtk_print_operation_get_default_page_setup (operation);
214

215
  print_size_info_set_page_setup (&info);
216
  print_preview_set_page_setup (PRINT_PREVIEW (info.preview), setup);
217 218
}

219 220 221 222 223 224 225 226 227
static void
update_custom_widget (GtkPrintOperation *operation,
                      GtkWidget         *custom_widget,
                      GtkPageSetup      *page_setup,
                      GtkPrintSettings  *print_settings)
{
  gtk_print_operation_set_default_page_setup (operation, page_setup);
}

228

229 230
#define SB_WIDTH 8

231
static GtkWidget *
232
print_size_frame (PrintData    *data,
233 234
                  GtkSizeGroup *label_group,
                  GtkSizeGroup *entry_group)
235
{
236 237 238 239 240 241 242
  GtkWidget     *entry;
  GtkWidget     *height;
  GtkWidget     *vbox;
  GtkWidget     *hbox;
  GtkWidget     *chain;
  GtkWidget     *frame;
  GtkWidget     *label;
243
  GtkWidget     *button;
244 245 246
  GtkAdjustment *adj;
  gdouble        image_width;
  gdouble        image_height;
247

248
  image_width  = (info.image_width *
249
                  gimp_unit_get_factor (data->unit) / data->xres);
250
  image_height = (info.image_height *
251
                  gimp_unit_get_factor (data->unit) / data->yres);
252

253
  frame = gimp_frame_new (_("Size"));
254

255
  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
Sven Neumann's avatar
Sven Neumann committed
256 257
  gtk_container_add (GTK_CONTAINER (frame), vbox);
  gtk_widget_show (vbox);
258

Sven Neumann's avatar
Sven Neumann committed
259
  /*  the print size entry  */
260

261
  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
Sven Neumann's avatar
Sven Neumann committed
262
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
263 264
  gtk_widget_show (hbox);

Sven Neumann's avatar
Sven Neumann committed
265 266
  entry = gimp_size_entry_new (1, data->unit, "%p",
                               FALSE, FALSE, FALSE, SB_WIDTH,
267
                               GIMP_SIZE_ENTRY_UPDATE_SIZE);
268 269 270
  gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
  gtk_widget_show (entry);

271
  info.size_entry = GIMP_SIZE_ENTRY (entry);
Sven Neumann's avatar
Sven Neumann committed
272

273
  gtk_grid_set_row_spacing (GTK_GRID (entry), 2);
Sven Neumann's avatar
Sven Neumann committed
274

275
  adj = gtk_adjustment_new (1, 1, 1, 1, 10, 0);
276 277
  height = gtk_spin_button_new (adj, 1, 2);
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (height), TRUE);
278 279
  gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry),
                             GTK_SPIN_BUTTON (height), NULL);
Simon Budig's avatar
Simon Budig committed
280
  gtk_grid_attach (GTK_GRID (entry), height, 1, 0, 1, 1);
281 282
  gtk_widget_show (height);

Sven Neumann's avatar
Sven Neumann committed
283 284 285 286 287 288 289 290
  gtk_size_group_add_widget (entry_group, height);

  gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (entry),
                                _("_Width:"), 0, 0, 0.0);
  label = gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (entry),
                                        _("_Height:"), 1, 0, 0.0);

  gtk_size_group_add_widget (label_group, label);
291 292 293 294 295 296

  gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (entry), 0,
                                  data->xres, FALSE);
  gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (entry), 1,
                                  data->yres, FALSE);

297 298
  gimp_size_entry_set_value (GIMP_SIZE_ENTRY (entry), 0, image_width);
  gimp_size_entry_set_value (GIMP_SIZE_ENTRY (entry), 1, image_height);
299 300 301

  /*  the resolution entry  */

302
  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
Sven Neumann's avatar
Sven Neumann committed
303
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
304 305
  gtk_widget_show (hbox);

306
  entry = gimp_size_entry_new (1, data->image_unit,
307
                               _("pixels/%a"),
308 309 310 311 312
                               FALSE, FALSE, FALSE, SB_WIDTH,
                               GIMP_SIZE_ENTRY_UPDATE_RESOLUTION);
  gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
  gtk_widget_show (entry);

313
  info.resolution_entry = GIMP_SIZE_ENTRY (entry);
Sven Neumann's avatar
Sven Neumann committed
314

315
  gtk_grid_set_row_spacing (GTK_GRID (entry), 2);
Sven Neumann's avatar
Sven Neumann committed
316

317
  adj = gtk_adjustment_new (1, 1, 1, 1, 10, 0);
318 319
  height = gtk_spin_button_new (adj, 1, 2);
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (height), TRUE);
320 321
  gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry),
                             GTK_SPIN_BUTTON (height), NULL);
322
  gtk_grid_attach (GTK_GRID (entry), height, 1, 0, 1, 1);
323 324
  gtk_widget_show (height);

Sven Neumann's avatar
Sven Neumann committed
325 326 327
  gtk_size_group_add_widget (entry_group, height);

  label = gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (entry),
Sven Neumann's avatar
Sven Neumann committed
328
                                        _("_X resolution:"), 0, 0, 0.0);
329
  gtk_size_group_add_widget (label_group, label);
Sven Neumann's avatar
Sven Neumann committed
330

331
  label = gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (entry),
Sven Neumann's avatar
Sven Neumann committed
332
                                        _("_Y resolution:"), 1, 0, 0.0);
Sven Neumann's avatar
Sven Neumann committed
333
  gtk_size_group_add_widget (label_group, label);
334

335 336 337 338 339 340 341
  button = gtk_button_new_with_mnemonic (_("_Load Defaults"));
  g_signal_connect_swapped (button, "clicked",
                            G_CALLBACK (print_resolution_load_defaults),
                            &info);
  gtk_widget_show (button);
  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);

342 343 344 345 346 347 348 349 350 351 352
  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, data->xres);
  gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (entry), 1, data->yres);

  chain = gimp_chain_button_new (GIMP_CHAIN_RIGHT);
353 354
  if (ABS (data->xres - data->yres) < GIMP_MIN_RESOLUTION)
    gimp_chain_button_set_active (GIMP_CHAIN_BUTTON (chain), TRUE);
355
  gtk_grid_attach (GTK_GRID (entry), chain, 2, 0, 1, 2);
356 357
  gtk_widget_show (chain);

358
  info.chain = GIMP_CHAIN_BUTTON (chain);
359

360
  g_signal_connect (info.resolution_entry, "value-changed",
361
                    G_CALLBACK (print_size_info_resolution_changed),
362
                    NULL);
363 364 365
  g_signal_connect (info.size_entry, "unit-changed",
                    G_CALLBACK (print_size_info_unit_changed),
                    NULL);
366

367 368 369
  return frame;
}

370
static GtkWidget *
371
print_offset_frame (PrintData    *data,
372 373
                    GtkSizeGroup *label_group,
                    GtkSizeGroup *entry_group)
374
{
375 376 377 378
  GtkWidget *entry;
  GtkWidget *spinner;
  GtkWidget *vbox;
  GtkWidget *hbox;
Simon Budig's avatar
Simon Budig committed
379
  GtkWidget *grid;
380 381
  GtkWidget *frame;
  GtkWidget *label;
382
  GtkWidget *combo;
383

384
  frame = gimp_frame_new (_("Position"));
385

386
  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
387 388 389 390 391
  gtk_container_add (GTK_CONTAINER (frame), vbox);
  gtk_widget_show (vbox);

  /*  the offset entry  */

392
  entry = GTK_WIDGET (info.size_entry);
393

Simon Budig's avatar
Simon Budig committed
394 395 396 397 398
  grid = gtk_grid_new ();
  gtk_grid_set_row_spacing (GTK_GRID (grid), 2);
  gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
  gtk_box_pack_start (GTK_BOX (vbox), grid, FALSE, FALSE, 0);
  gtk_widget_show (grid);
399

400
  /* left */
401
  info.left_adj = gtk_adjustment_new (1, 1, 1, 1, 10, 0);
402 403
  spinner = gtk_spin_button_new (info.left_adj, 1, 2);
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinner), TRUE);
404

405 406
  gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry),
                             GTK_SPIN_BUTTON (spinner), NULL);
Simon Budig's avatar
Simon Budig committed
407
  gtk_grid_attach (GTK_GRID (grid), spinner, 1, 0, 1, 1);
408
  gtk_widget_show (spinner);
409

410 411
  label = gtk_label_new_with_mnemonic (_("_Left:"));
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinner);
412
  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
Simon Budig's avatar
Simon Budig committed
413
  gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
414 415 416 417
  gtk_size_group_add_widget (label_group, label);
  gtk_widget_show (label);

  /* right */
418
  info.right_adj = gtk_adjustment_new (1, 1, 1, 1, 10, 0);
419 420
  spinner = gtk_spin_button_new (info.right_adj, 1, 2);
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinner), TRUE);
421

422
  g_signal_connect (info.right_adj, "value-changed",
423 424
                    G_CALLBACK (print_size_info_offset_max_changed),
                    GINT_TO_POINTER (LEFT));
425 426

  gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry),
427
                             GTK_SPIN_BUTTON (spinner), NULL);
Simon Budig's avatar
Simon Budig committed
428
  gtk_grid_attach (GTK_GRID (grid), spinner, 3, 0, 1, 1);
429
  gtk_widget_show (spinner);
430

431 432
  label = gtk_label_new_with_mnemonic (_("_Right:"));
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinner);
433
  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
Simon Budig's avatar
Simon Budig committed
434
  gtk_grid_attach (GTK_GRID (grid), label, 2, 0, 1, 1);
435
  gtk_widget_show (label);
436

437
  /* top */
438
  info.top_adj = gtk_adjustment_new (1, 1, 1, 1, 10, 0);
439 440
  spinner = gtk_spin_button_new (info.top_adj, 1, 2);
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinner), TRUE);
441

442 443
  gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry),
                             GTK_SPIN_BUTTON (spinner), NULL);
Simon Budig's avatar
Simon Budig committed
444
  gtk_grid_attach (GTK_GRID (grid), spinner, 1, 1, 1, 1);
445
  gtk_widget_show (spinner);
446

447 448
  label = gtk_label_new_with_mnemonic (_("_Top:"));
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinner);
449
  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
Simon Budig's avatar
Simon Budig committed
450
  gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
451
  gtk_size_group_add_widget (label_group, label);
452
  gtk_widget_show (label);
453

454
  /* bottom */
455
  info.bottom_adj = gtk_adjustment_new (1, 1, 1, 1, 10, 0);
456 457
  spinner = gtk_spin_button_new (info.bottom_adj, 1, 2);
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinner), TRUE);
458

459
  g_signal_connect (info.bottom_adj, "value-changed",
460 461 462 463 464
                    G_CALLBACK (print_size_info_offset_max_changed),
                    GINT_TO_POINTER (TOP));

  gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry),
                             GTK_SPIN_BUTTON (spinner), NULL);
Simon Budig's avatar
Simon Budig committed
465
  gtk_grid_attach (GTK_GRID (grid), spinner, 3, 1, 1, 1);
466 467 468 469
  gtk_widget_show (spinner);

  label = gtk_label_new_with_mnemonic (_("_Bottom:"));
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinner);
470
  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
Simon Budig's avatar
Simon Budig committed
471
  gtk_grid_attach (GTK_GRID (grid), label, 2, 1, 1, 1);
472
  gtk_widget_show (label);
473

474 475 476 477
  gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (entry), LEFT,   72.0, FALSE);
  gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (entry), RIGHT,  72.0, FALSE);
  gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (entry), TOP,    72.0, FALSE);
  gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (entry), BOTTOM, 72.0, FALSE);
478

479 480 481 482
  print_size_info_update_offsets ();

  g_signal_connect (info.size_entry, "value-changed",
                    G_CALLBACK (print_size_info_size_changed),
483 484
                    NULL);

485
  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
486 487 488
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  gtk_widget_show (hbox);

489
  label = gtk_label_new_with_mnemonic (_("C_enter:"));
490
  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
491
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
492
  gtk_size_group_add_widget (label_group, label);
493 494
  gtk_widget_show (label);

495
  /*  if and how to center the image on the page  */
496 497 498 499
  combo = gimp_int_combo_box_new (C_("center-mode", "None"), CENTER_NONE,
                                  _("Horizontally"),         CENTER_HORIZONTALLY,
                                  _("Vertically"),           CENTER_VERTICALLY,
                                  _("Both"),                 CENTER_BOTH,
500 501 502
                                  NULL);
  gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
  gtk_widget_show (combo);
503

504
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
505

506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
                              data->center,
                              G_CALLBACK (print_size_info_center_changed),
                              NULL);

  info.center_combo = combo;

  g_signal_connect (info.left_adj, "value-changed",
                    G_CALLBACK (print_size_info_center_none),
                    NULL);
  g_signal_connect (info.right_adj, "value-changed",
                    G_CALLBACK (print_size_info_center_none),
                    NULL);
  g_signal_connect (info.top_adj, "value-changed",
                    G_CALLBACK (print_size_info_center_none),
                    NULL);
  g_signal_connect (info.bottom_adj, "value-changed",
                    G_CALLBACK (print_size_info_center_none),
                    NULL);
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542

  return frame;
}

static void
print_size_info_get_page_dimensions (PrintSizeInfo *info,
                                     gdouble       *page_width,
                                     gdouble       *page_height,
                                     GtkUnit        unit)
{
  GtkPageSetup *setup;

  setup = gtk_print_operation_get_default_page_setup (info->data->operation);

  if (info->data->use_full_page)
    {
      *page_width = gtk_page_setup_get_paper_width (setup, unit);
      *page_height = gtk_page_setup_get_paper_height (setup, unit);
543 544 545
    }
  else
    {
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
      *page_width = gtk_page_setup_get_page_width (setup, unit);
      *page_height = gtk_page_setup_get_page_height (setup, unit);
    }

}

static void
gimp_size_info_get_max_offsets (gdouble *offset_x_max,
                                gdouble *offset_y_max)
{
  gdouble width;
  gdouble height;

  print_size_info_get_page_dimensions (&info, &width, &height, GTK_UNIT_POINTS);

  *offset_x_max = width - 72.0 * info.image_width / info.data->xres;
  *offset_x_max = MAX (0, *offset_x_max);

  *offset_y_max = height - 72.0 * info.image_height / info.data->yres;
  *offset_y_max = MAX (0, *offset_y_max);
}

568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
static void
print_size_info_center_none_block (void)
{
  g_signal_handlers_block_by_func (info.left_adj,
                                   print_size_info_center_none, NULL);
  g_signal_handlers_block_by_func (info.right_adj,
                                   print_size_info_center_none, NULL);
  g_signal_handlers_block_by_func (info.top_adj,
                                   print_size_info_center_none, NULL);
  g_signal_handlers_block_by_func (info.bottom_adj,
                                   print_size_info_center_none, NULL);
}

static void
print_size_info_center_none_unblock (void)
{
  g_signal_handlers_unblock_by_func (info.left_adj,
                                     print_size_info_center_none, NULL);
  g_signal_handlers_unblock_by_func (info.right_adj,
                                     print_size_info_center_none, NULL);
  g_signal_handlers_unblock_by_func (info.top_adj,
                                     print_size_info_center_none, NULL);
  g_signal_handlers_unblock_by_func (info.bottom_adj,
                                     print_size_info_center_none, NULL);
}

594
static void
595 596
print_size_info_update_offsets (void)
{
597 598 599
  PrintData *data = info.data;
  gdouble    offset_x_max;
  gdouble    offset_y_max;
600 601 602 603 604 605

  gimp_size_info_get_max_offsets (&offset_x_max, &offset_y_max);

  g_signal_handlers_block_by_func (info.size_entry,
                                   print_size_info_size_changed, NULL);

606
  print_size_info_center_none_block ();
607

608 609 610 611 612 613 614 615 616
  gimp_size_entry_set_refval_boundaries (info.size_entry, LEFT,
                                         0, offset_x_max);
  gimp_size_entry_set_refval_boundaries (info.size_entry, RIGHT,
                                         0, offset_x_max);
  gimp_size_entry_set_refval_boundaries (info.size_entry, TOP,
                                         0, offset_y_max);
  gimp_size_entry_set_refval_boundaries (info.size_entry, BOTTOM,
                                         0, offset_y_max);

617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
  switch (data->center)
    {
    case CENTER_NONE:
      break;

    case CENTER_HORIZONTALLY:
      data->offset_x = offset_x_max / 2.0;
      break;

    case CENTER_VERTICALLY:
      data->offset_y = offset_y_max / 2.0;
      break;

    case CENTER_BOTH:
      data->offset_x = offset_x_max / 2.0;
      data->offset_y = offset_y_max / 2.0;
      break;
    }

636
  gimp_size_entry_set_refval (info.size_entry, LEFT,
637
                              data->offset_x);
638
  gimp_size_entry_set_refval (info.size_entry, RIGHT,
639
                              offset_x_max - data->offset_x);
640 641 642
  gimp_size_entry_set_refval (info.size_entry, TOP,
                              info.data->offset_y);
  gimp_size_entry_set_refval (info.size_entry, BOTTOM,
643 644
                              offset_y_max - data->offset_y);

645
  print_size_info_center_none_unblock ();
646 647 648 649 650 651

  g_signal_handlers_unblock_by_func (info.size_entry,
                                     print_size_info_size_changed, NULL);
}

static void
652
print_size_info_center_changed (GtkWidget *combo)
653
{
654
  gint value;
655

656
  if (gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (combo), &value))
657
    {
658 659 660 661 662
      info.data->center = value;

      print_size_info_update_offsets ();

      if (info.preview)
663 664 665
        print_preview_set_image_offsets (PRINT_PREVIEW (info.preview),
                                         info.data->offset_x,
                                         info.data->offset_y);
666
    }
667
}
668

669 670 671
static void
print_size_info_center_none (void)
{
672 673 674 675
  /* return early if we are called from a unit change */
  if (gimp_size_entry_get_unit (info.size_entry) != info.data->unit)
    return;

676
  info.data->center = CENTER_NONE;
677

678 679 680 681 682 683 684 685 686 687 688 689 690
  if (info.center_combo)
    {
      g_signal_handlers_block_by_func (info.center_combo,
                                       print_size_info_center_changed, NULL);

      info.data->center = CENTER_NONE;

      gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (info.center_combo),
                                     info.data->center);

      g_signal_handlers_unblock_by_func (info.center_combo,
                                         print_size_info_center_changed, NULL);
    }
691 692
}

693 694 695 696 697
static void
print_size_info_preview_offset_changed (GtkWidget *widget,
                                        gdouble    offset_x,
                                        gdouble    offset_y)
{
698
  print_size_info_center_none ();
699 700 701 702 703 704 705

  info.data->offset_x = offset_x;
  info.data->offset_y = offset_y;

  print_size_info_update_offsets ();
}

706
static void
707
print_size_info_size_changed (GtkWidget *widget)
708
{
709 710 711 712 713
  gdouble width;
  gdouble height;
  gdouble xres;
  gdouble yres;
  gdouble scale;
714

715
  scale = gimp_unit_get_factor (gimp_size_entry_get_unit (info.size_entry));
716

717 718
  width  = gimp_size_entry_get_value (info.size_entry, WIDTH);
  height = gimp_size_entry_get_value (info.size_entry, HEIGHT);
719

720 721
  xres = scale * info.image_width  / MAX (0.0001, width);
  yres = scale * info.image_height / MAX (0.0001, height);
722

723
  print_size_info_set_resolution (&info, xres, yres);
724 725 726 727

  info.data->offset_x = gimp_size_entry_get_refval (info.size_entry, LEFT);
  info.data->offset_y = gimp_size_entry_get_refval (info.size_entry, TOP);

728 729 730
  print_preview_set_image_offsets (PRINT_PREVIEW (info.preview),
                                   info.data->offset_x,
                                   info.data->offset_y);
731 732 733 734 735 736
}

static void
print_size_info_offset_max_changed (GtkAdjustment *adj,
                                    gpointer       data)
{
737
  guint index = GPOINTER_TO_INT (data);
738

739 740 741 742
  /* return early if we are called from a unit change */
  if (gimp_size_entry_get_unit (info.size_entry) != info.data->unit)
    return;

743 744 745
  g_signal_handlers_block_by_func (info.size_entry,
                                   print_size_info_size_changed, NULL);

746 747 748
  gimp_size_entry_set_value (info.size_entry, index,
                             gtk_adjustment_get_upper (adj) -
                             gtk_adjustment_get_value (adj));
749 750 751

  g_signal_handlers_unblock_by_func (info.size_entry,
                                     print_size_info_size_changed, NULL);
752 753 754
}

static void
755
print_size_info_resolution_changed (GtkWidget *widget)
756
{
757
  GimpSizeEntry *entry = info.resolution_entry;
758 759 760
  gdouble        xres  = gimp_size_entry_get_refval (entry, 0);
  gdouble        yres  = gimp_size_entry_get_refval (entry, 1);

761
  print_size_info_set_resolution (&info, xres, yres);
762 763
}

764
static void
765
print_size_info_use_full_page_toggled (GtkWidget *widget)
766
{
767
  gboolean active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
768 769 770

  info.data->use_full_page = active;

771
  print_size_info_set_page_setup (&info);
772

773
  print_preview_set_use_full_page (PRINT_PREVIEW(info.preview), active);
774 775
}

776 777 778 779 780 781 782 783
static void
print_size_info_unit_changed (GtkWidget *widget)
{
  info.data->unit = gimp_size_entry_get_unit (GIMP_SIZE_ENTRY (widget));

  print_size_info_set_page_setup (&info);
}

784 785 786 787 788
static void
print_size_info_set_resolution (PrintSizeInfo *info,
                                gdouble        xres,
                                gdouble        yres)
{
789 790 791 792 793
  PrintData *data = info->data;
  gdouble    offset_x;
  gdouble    offset_y;
  gdouble    offset_x_max;
  gdouble    offset_y_max;
794

795 796 797
  if (info->chain && gimp_chain_button_get_active (info->chain))
    {
      if (xres != data->xres)
798
        yres = xres;
799
      else
800
        xres = yres;
801 802 803 804 805 806 807
    }

  data->xres = xres;
  data->yres = yres;

  g_signal_handlers_block_by_func (info->resolution_entry,
                                   print_size_info_resolution_changed,
808
                                   NULL);
809 810 811 812 813 814

  gimp_size_entry_set_refval (info->resolution_entry, 0, xres);
  gimp_size_entry_set_refval (info->resolution_entry, 1, yres);

  g_signal_handlers_unblock_by_func (info->resolution_entry,
                                     print_size_info_resolution_changed,
815
                                     NULL);
816 817 818

  g_signal_handlers_block_by_func (info->size_entry,
                                   print_size_info_size_changed,
819
                                   NULL);
820

821
  gimp_size_entry_set_value (info->size_entry, WIDTH,
822
                             info->image_width *
823
                             gimp_unit_get_factor (data->unit) / xres);
824
  gimp_size_entry_set_value (info->size_entry, HEIGHT,
825
                             info->image_height *
826
                             gimp_unit_get_factor (data->unit) / yres);
827 828 829

  g_signal_handlers_unblock_by_func (info->size_entry,
                                     print_size_info_size_changed,
830
                                     NULL);
831 832 833

  gimp_size_info_get_max_offsets (&offset_x_max, &offset_y_max);

834 835
  offset_x = gimp_size_entry_get_refval (info->size_entry, LEFT);
  offset_y = gimp_size_entry_get_refval (info->size_entry, TOP);
836 837 838 839 840 841 842

  offset_x = CLAMP (offset_x, 0, offset_x_max);
  offset_y = CLAMP (offset_y, 0, offset_y_max);

  data->offset_x = offset_x;
  data->offset_y = offset_y;

843
  print_size_info_update_offsets ();
844

845 846 847 848 849 850
  print_preview_set_image_dpi (PRINT_PREVIEW (info->preview),
                               data->xres, data->yres);
  print_preview_set_image_offsets (PRINT_PREVIEW (info->preview),
                                   data->offset_x, data->offset_y);
  print_preview_set_image_offsets_max (PRINT_PREVIEW (info->preview),
                                       offset_x_max, offset_y_max);
851 852 853
}

static void
854
print_size_info_set_page_setup (PrintSizeInfo *info)
855
{
856 857 858 859 860 861
  PrintData    *data = info->data;
  gdouble       page_width;
  gdouble       page_height;
  gdouble       x;
  gdouble       y;

862 863 864
  print_size_info_get_page_dimensions (info,
                                       &page_width, &page_height,
                                       GTK_UNIT_INCH);
865 866 867

  page_width  *= gimp_unit_get_factor (data->unit);
  page_height *= gimp_unit_get_factor (data->unit);
868

869 870 871 872 873 874 875 876 877 878 879 880 881 882 883
  if (info->area_label)
    {
      gchar *format;
      gchar *text;

      format = g_strdup_printf ("%%.%df x %%.%df %s",
                                gimp_unit_get_digits (data->unit),
                                gimp_unit_get_digits (data->unit),
                                gimp_unit_get_plural (data->unit));
      text = g_strdup_printf (format, page_width, page_height);
      g_free (format);

      gtk_label_set_text (GTK_LABEL (info->area_label), text);
      g_free (text);
    }
884 885 886 887 888 889

  x = page_width;
  y = page_height;

  if (info->chain && gimp_chain_button_get_active (info->chain))
    {
890
      gdouble ratio_x = page_width  / (gdouble) info->image_width;
891
      gdouble ratio_y = page_height / (gdouble) info->image_height;
892

893 894
      if (ratio_x < ratio_y)
        y = (gdouble) info->image_height * ratio_x;
895
      else
Sven Neumann's avatar
Sven Neumann committed
896
        x = (gdouble) info->image_width  * ratio_y;
897 898
    }

Sven Neumann's avatar
Sven Neumann committed
899 900 901 902
  gimp_size_entry_set_value_boundaries (info->size_entry, WIDTH,
                                        page_width  / 100.0, x);
  gimp_size_entry_set_value_boundaries (info->size_entry, HEIGHT,
                                        page_height / 100.0, y);
903

904 905 906
  print_size_info_get_page_dimensions (info,
                                       &page_width, &page_height,
                                       GTK_UNIT_POINTS);
907

Sven Neumann's avatar
Sven Neumann committed
908
  x = (gdouble) info->image_width  / page_width  * 72.0;
909
  y = (gdouble) info->image_height / page_height * 72.0;
910 911 912 913 914 915 916 917

  if (info->chain && gimp_chain_button_get_active (info->chain))
    {
      gdouble max = MAX (x, y);

      x = y = max;
    }

918 919
  data->min_xres = x;
  data->min_yres = y;
920 921 922 923
  gimp_size_entry_set_refval_boundaries (info->resolution_entry, 0,
                                         x, GIMP_MAX_RESOLUTION);
  gimp_size_entry_set_refval_boundaries (info->resolution_entry, 1,
                                         y, GIMP_MAX_RESOLUTION);
924
}
925 926 927 928 929 930 931 932 933

static void
print_draw_crop_marks_toggled (GtkWidget *widget)
{
  gboolean active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));

  info.data->draw_crop_marks = active;
}

934 935 936 937 938 939 940 941 942 943 944 945
static void
print_resolution_load_defaults (PrintSizeInfo *info)
{
  gdouble xres;
  gdouble yres;

  gimp_image_get_resolution (info->data->image_id, &xres, &yres);

  gimp_size_entry_set_refval (info->resolution_entry, 0, xres);
  gimp_size_entry_set_refval (info->resolution_entry, 1, yres);
  print_size_info_resolution_changed (GTK_WIDGET (info->resolution_entry));
}