]> git.street.me.uk Git - andy/viking.git/blame - src/print.c
[QA] CID#101114+CID#101115: Result not floating point
[andy/viking.git] / src / print.c
CommitLineData
42f34743
QT
1/*
2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3 *
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
5 *
6 * print.c
7 * Copyright (C) 2007, Quy Tonthat <qtonthat@gmail.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
4c77d5e0
GB
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
9a995996 27
42f34743
QT
28#include <string.h>
29#include <glib/gprintf.h>
4c77d5e0
GB
30#include <glib/gi18n.h>
31#include <gtk/gtk.h>
32
42f34743
QT
33#include "viking.h"
34#include "print.h"
35#include "print-preview.h"
36
37typedef enum
38{
39 VIK_PRINT_CENTER_NONE = 0,
40 VIK_PRINT_CENTER_HORIZONTALLY,
41 VIK_PRINT_CENTER_VERTICALLY,
42 VIK_PRINT_CENTER_BOTH,
43} PrintCenterMode;
44
45typedef struct {
46 gchar *name;
47 PrintCenterMode mode;
48} PrintCenterName;
49
50static const PrintCenterName center_modes[] = {
4c77d5e0
GB
51 {N_("None"), VIK_PRINT_CENTER_NONE},
52 {N_("Horizontally"), VIK_PRINT_CENTER_HORIZONTALLY},
53 {N_("Vertically"), VIK_PRINT_CENTER_VERTICALLY},
54 {N_("Both"), VIK_PRINT_CENTER_BOTH},
42f34743
QT
55 {NULL, -1}
56};
57
58typedef struct {
59 gint num_pages;
60 gboolean show_info_header;
61 VikWindow *vw;
62 VikViewport *vvp;
63 gdouble xmpp, ympp; /* zoom level (meters/pixel) */
64 gdouble xres;
65 gdouble yres;
66 gint width;
67 gint height;
68 gdouble offset_x;
69 gdouble offset_y;
70 PrintCenterMode center;
71 gboolean use_full_page;
72 GtkPrintOperation *operation;
73} PrintData;
74
75static GtkWidget *create_custom_widget_cb(GtkPrintOperation *operation, PrintData *data);
76static void begin_print(GtkPrintOperation *operation, GtkPrintContext *context, PrintData *data);
77static void draw_page(GtkPrintOperation *print, GtkPrintContext *context, gint page_nr, PrintData *data);
78static void end_print(GtkPrintOperation *operation, GtkPrintContext *context, PrintData *data);
79
80void a_print(VikWindow *vw, VikViewport *vvp)
81{
82 /* TODO: make print_settings non-static when saving_settings_to_file is
83 * implemented. Keep it static for now to retain settings for each
84 * viking session
85 */
86 static GtkPrintSettings *print_settings = NULL;
87
88 GtkPrintOperation *print_oper;
89 GtkPrintOperationResult res;
90 PrintData data;
91
92 print_oper = gtk_print_operation_new ();
93
94 data.num_pages = 1;
95 data.vw = vw;
96 data.vvp = vvp;
97 data.offset_x = 0;
98 data.offset_y = 0;
99 data.center = VIK_PRINT_CENTER_BOTH;
100 data.use_full_page = FALSE;
101 data.operation = print_oper;
102
103 data.xmpp = vik_viewport_get_xmpp(vvp);
104 data.ympp = vik_viewport_get_ympp(vvp);
105 data.width = vik_viewport_get_width(vvp);
106 data.height = vik_viewport_get_height(vvp);
107
436fa17a 108 data.xres = data.yres = 1; // This forces it to default to a 100% page size
42f34743
QT
109
110 if (print_settings != NULL)
111 gtk_print_operation_set_print_settings (print_oper, print_settings);
112
113 g_signal_connect (print_oper, "begin_print", G_CALLBACK (begin_print), &data);
114 g_signal_connect (print_oper, "draw_page", G_CALLBACK (draw_page), &data);
115 g_signal_connect (print_oper, "end-print", G_CALLBACK (end_print), &data);
116 g_signal_connect (print_oper, "create-custom-widget", G_CALLBACK (create_custom_widget_cb), &data);
117
7760b0cf 118 gtk_print_operation_set_custom_tab_label (print_oper, _("Image Settings"));
42f34743
QT
119
120 res = gtk_print_operation_run (print_oper,
121 GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
122 GTK_WINDOW (vw), NULL);
123
124 if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
125 if (print_settings != NULL)
126 g_object_unref (print_settings);
127 print_settings = g_object_ref (gtk_print_operation_get_print_settings (print_oper));
128 }
129
130 g_object_unref (print_oper);
131}
132
133static void begin_print(GtkPrintOperation *operation,
134 GtkPrintContext *context,
135 PrintData *data)
136{
137 // fputs("DEBUG: begin_print() called\n", stderr);
138 gtk_print_operation_set_n_pages (operation, data->num_pages);
139 gtk_print_operation_set_use_full_page (operation, data->use_full_page);
140
141}
142
143static void end_print(GtkPrintOperation *operation,
144 GtkPrintContext *context,
145 PrintData *data)
146{
147 // fputs("DEBUG: end_print() called\n", stderr);
148
149}
150
151static void copy_row_from_rgb(guchar *surface_pixels, guchar *pixbuf_pixels, gint width)
152{
153 guint32 *cairo_data = (guint32 *) surface_pixels;
154 guchar *p;
155 gint i;
156
157 for (i = 0, p = pixbuf_pixels; i < width; i++) {
158 guint32 r = *p++;
159 guint32 g = *p++;
160 guint32 b = *p++;
161 cairo_data[i] = 0xFF000000 | (r << 16) | (g << 8) | b;
162 }
163}
164
165#define INT_MULT(a,b,t) ((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8))
166#define INT_BLEND(a,b,alpha,tmp) (INT_MULT((a) - (b), alpha, tmp) + (b))
167static void copy_row_from_rgba(guchar *surface_pixels, guchar *pixbuf_pixels, gint width)
168{
169 guint32 *cairo_data = (guint32 *) surface_pixels;
170 guchar *p;
171 gint i;
172
173 for (i = 0, p = pixbuf_pixels; i < width; i++) {
174 guint32 r = *p++;
175 guint32 g = *p++;
176 guint32 b = *p++;
177 guint32 a = *p++;
178
179 if (a != 255) {
180 guint32 tmp;
181 /* composite on a white background */
182 r = INT_BLEND (r, 255, a, tmp);
183 g = INT_BLEND (g, 255, a, tmp);
184 b = INT_BLEND (b, 255, a, tmp);
185 }
186 cairo_data[i] = 0xFF000000 | (r << 16) | (g << 8) | b;
187 }
188}
189
190static void draw_page_cairo(GtkPrintContext *context, PrintData *data)
191{
192 cairo_t *cr;
193 GdkPixbuf *pixbuf_to_draw;
194 cairo_surface_t *surface;
195 guchar *surface_pixels;
196 guchar *pixbuf_pixels;
197 gint stride;
198 gint pixbuf_stride;
199 gint pixbuf_n_channels;
42f34743
QT
200 gdouble cr_dpi_x;
201 gdouble cr_dpi_y;
202 gdouble scale_x;
203 gdouble scale_y;
204 gint y;
205
206 cr = gtk_print_context_get_cairo_context(context);
207 pixbuf_to_draw = gdk_pixbuf_get_from_drawable(NULL,
208 GDK_DRAWABLE(vik_viewport_get_pixmap(data->vvp)),
209 NULL, 0, 0, 0, 0, data->width, data->height);
210 surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
211 data->width, data->height);
212
42f34743
QT
213 cr_dpi_x = gtk_print_context_get_dpi_x (context);
214 cr_dpi_y = gtk_print_context_get_dpi_y (context);
215
216 scale_x = cr_dpi_x / data->xres;
217 scale_y = cr_dpi_y / data->yres;
218
219 cairo_translate (cr,
220 data->offset_x / cr_dpi_x * 72.0,
221 data->offset_y / cr_dpi_y * 72.0);
222 cairo_scale (cr, scale_x, scale_y);
223
224 surface_pixels = cairo_image_surface_get_data (surface);
225 stride = cairo_image_surface_get_stride (surface);
226 pixbuf_pixels = gdk_pixbuf_get_pixels (pixbuf_to_draw);
227 pixbuf_stride = gdk_pixbuf_get_rowstride(pixbuf_to_draw);
228 pixbuf_n_channels = gdk_pixbuf_get_n_channels(pixbuf_to_draw);
229
230 // fprintf(stderr, "DEBUG: %s() surface_pixels=%p pixbuf_pixels=%p size=%d surface_width=%d surface_height=%d stride=%d data_height=%d pixmap_stride=%d pixmap_nchannels=%d pixmap_bit_per_Sample=%d\n", __PRETTY_FUNCTION__, surface_pixels, pixbuf_pixels, stride * data->height, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface), stride, data->height, gdk_pixbuf_get_rowstride(pixbuf_to_draw), gdk_pixbuf_get_n_channels(pixbuf_to_draw), gdk_pixbuf_get_bits_per_sample(pixbuf_to_draw));
231
232 /* Assume the pixbuf has 8 bits per channel */
233 for (y = 0; y < data->height; y++, surface_pixels += stride, pixbuf_pixels += pixbuf_stride) {
234 switch (pixbuf_n_channels) {
235 case 3:
236 copy_row_from_rgb (surface_pixels, pixbuf_pixels, data->width);
237 break;
238 case 4:
239 copy_row_from_rgba (surface_pixels, pixbuf_pixels, data->width);
240 break;
9351abc4 241 default: break;
42f34743
QT
242 }
243 }
244
245 g_object_unref(G_OBJECT(pixbuf_to_draw));
246
247 cairo_set_source_surface(cr, surface, 0, 0);
248 cairo_rectangle(cr, 0, 0, data->width, data->height);
249 cairo_fill(cr);
250 cairo_surface_destroy(surface);
251}
252
253static void draw_page(GtkPrintOperation *print,
254 GtkPrintContext *context,
255 gint page_nr,
256 PrintData *data)
257{
258 // fprintf(stderr, "DEBUG: draw_page() page_nr=%d\n", page_nr);
259 draw_page_cairo(context, data);
260
261}
262
263/*********************** page layout gui *********************/
264typedef struct
265{
266 PrintData *data;
267 GtkWidget *center_combo;
268 GtkWidget *scale;
269 GtkWidget *scale_label;
270 GtkWidget *preview;
271} CustomWidgetInfo;
272
273enum
274{
275 BOTTOM,
276 TOP,
277 RIGHT,
278 LEFT,
279 WIDTH,
280 HEIGHT
281};
282
283static gboolean scale_change_value_cb(GtkRange *range, GtkScrollType scroll, gdouble value, CustomWidgetInfo *pinfo);
284static void get_page_dimensions (CustomWidgetInfo *info, gdouble *page_width, gdouble *page_height, GtkUnit unit);
285static void center_changed_cb (GtkWidget *combo, CustomWidgetInfo *info);
286static void get_max_offsets (CustomWidgetInfo *info, gdouble *offset_x_max, gdouble *offset_y_max);
287static void update_offsets (CustomWidgetInfo *info);
288
289static void set_scale_label(CustomWidgetInfo *pinfo, gdouble scale_val)
290{
291 static const gdouble inch_to_mm = 25.4;
292 gchar label_text[64];
293
294 g_snprintf(label_text, sizeof(label_text), "<i>%.0fx%0.f mm (%.0f%%)</i>",
295 inch_to_mm * pinfo->data->width / pinfo->data->xres,
296 inch_to_mm * pinfo->data->height / pinfo->data->yres,
297 scale_val);
298 gtk_label_set_markup (GTK_LABEL (pinfo->scale_label), label_text);
299}
300
301static void set_scale_value(CustomWidgetInfo *pinfo)
302{
303 gdouble width;
304 gdouble height;
305 gdouble ratio, ratio_w, ratio_h;
306
307
308 get_page_dimensions (pinfo, &width, &height, GTK_UNIT_INCH);
309 ratio_w = 100 * pinfo->data->width / pinfo->data->xres / width;
310 ratio_h = 100 * pinfo->data->height / pinfo->data->yres / height;
311
312 ratio = MAX(ratio_w, ratio_h);
313 g_signal_handlers_block_by_func(GTK_RANGE(pinfo->scale), scale_change_value_cb, pinfo);
314 gtk_range_set_value(GTK_RANGE(pinfo->scale), ratio);
315 g_signal_handlers_unblock_by_func(GTK_RANGE(pinfo->scale), scale_change_value_cb, pinfo);
316 set_scale_label(pinfo, ratio);
317}
318
319static void update_page_setup (CustomWidgetInfo *pinfo)
320{
321 gdouble paper_width;
322 gdouble paper_height;
323 gdouble offset_x_max, offset_y_max;
324 PrintData *data = pinfo->data;
325
326 get_page_dimensions (pinfo, &paper_width, &paper_height, GTK_UNIT_INCH);
327 if ((paper_width < (pinfo->data->width / data->xres)) ||
328 (paper_height < (pinfo->data->height / data->yres))) {
329 gdouble xres, yres;
330 xres = (gdouble) pinfo->data->width / paper_width;
331 yres = (gdouble) pinfo->data->height / paper_height;
332 data->xres = data->yres = MAX(xres, yres);
333 vik_print_preview_set_image_dpi (VIK_PRINT_PREVIEW (pinfo->preview),
334 data->xres, data->yres);
335 }
336 get_max_offsets (pinfo, &offset_x_max, &offset_y_max);
337 vik_print_preview_set_image_offsets_max (VIK_PRINT_PREVIEW (pinfo->preview),
338 offset_x_max, offset_y_max);
339 update_offsets (pinfo);
340 set_scale_value(pinfo);
341 if (pinfo->preview)
342 vik_print_preview_set_image_offsets (VIK_PRINT_PREVIEW (pinfo->preview),
343 pinfo->data->offset_x, pinfo->data->offset_y);
344
345}
346
347static void page_setup_cb (GtkWidget *widget, CustomWidgetInfo *info)
348{
349 PrintData *data = info->data;
350 GtkPrintOperation *operation = data->operation;
351 GtkPrintSettings *settings;
352 GtkPageSetup *page_setup;
353 GtkWidget *toplevel;
354
355 toplevel = gtk_widget_get_toplevel (widget);
2fd7c35e
RN
356#if GTK_CHECK_VERSION (2,18,0)
357 if (! gtk_widget_is_toplevel (toplevel))
358#else
42f34743 359 if (! GTK_WIDGET_TOPLEVEL (toplevel))
2fd7c35e 360#endif
42f34743
QT
361 toplevel = NULL;
362
363 settings = gtk_print_operation_get_print_settings (operation);
364 if (! settings)
365 settings = gtk_print_settings_new ();
366
367 page_setup = gtk_print_operation_get_default_page_setup (operation);
368
369 page_setup = gtk_print_run_page_setup_dialog (GTK_WINDOW (toplevel),
370 page_setup, settings);
371
372 gtk_print_operation_set_default_page_setup (operation, page_setup);
373
374 vik_print_preview_set_page_setup (VIK_PRINT_PREVIEW (info->preview),
375 page_setup);
376
377 update_page_setup (info);
378
379}
380
381static void full_page_toggled_cb (GtkWidget *widget, CustomWidgetInfo *pinfo)
382{
383 gboolean active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
384
385 pinfo->data->use_full_page = active;
386 update_page_setup (pinfo);
387 vik_print_preview_set_use_full_page (VIK_PRINT_PREVIEW(pinfo->preview),
388 active);
389}
390
391static void set_center_none (CustomWidgetInfo *info)
392{
393 info->data->center = VIK_PRINT_CENTER_NONE;
394
395 if (info->center_combo) {
396 g_signal_handlers_block_by_func (info->center_combo,
397 center_changed_cb, info);
398
399 info->data->center = VIK_PRINT_CENTER_NONE;
400 gtk_combo_box_set_active(GTK_COMBO_BOX(info->center_combo), info->data->center);
401 g_signal_handlers_unblock_by_func (info->center_combo,
402 center_changed_cb, info);
403 }
404}
405
406static void preview_offsets_changed_cb (GtkWidget *widget,
407 gdouble offset_x, gdouble offset_y,
408 CustomWidgetInfo *info)
409{
410 set_center_none (info);
411
412 info->data->offset_x = offset_x;
413 info->data->offset_y = offset_y;
414
415 update_offsets (info);
416
417}
418
419static void get_page_dimensions (CustomWidgetInfo *info,
420 gdouble *page_width,
421 gdouble *page_height,
422 GtkUnit unit)
423{
424 GtkPageSetup *setup;
425
426 setup = gtk_print_operation_get_default_page_setup (info->data->operation);
427
428 *page_width = gtk_page_setup_get_paper_width (setup, unit);
429 *page_height = gtk_page_setup_get_paper_height (setup, unit);
430
431 if (!info->data->use_full_page) {
432 gdouble left_margin = gtk_page_setup_get_left_margin (setup, unit);
433 gdouble right_margin = gtk_page_setup_get_right_margin (setup, unit);
434 gdouble top_margin = gtk_page_setup_get_top_margin (setup, unit);
435 gdouble bottom_margin = gtk_page_setup_get_bottom_margin (setup, unit);
436
437 *page_width -= left_margin + right_margin;
438 *page_height -= top_margin + bottom_margin;
439 }
440
441}
442
443static void get_max_offsets (CustomWidgetInfo *info,
444 gdouble *offset_x_max,
445 gdouble *offset_y_max)
446{
447 gdouble width;
448 gdouble height;
449
450 get_page_dimensions (info, &width, &height, GTK_UNIT_POINTS);
451
452 *offset_x_max = width - 72.0 * info->data->width / info->data->xres;
453 *offset_x_max = MAX (0, *offset_x_max);
454
455 *offset_y_max = height - 72.0 * info->data->height / info->data->yres;
456 *offset_y_max = MAX (0, *offset_y_max);
457}
458
459static void update_offsets (CustomWidgetInfo *info)
460{
461 PrintData *data = info->data;
462 gdouble offset_x_max;
463 gdouble offset_y_max;
464
465 get_max_offsets (info, &offset_x_max, &offset_y_max);
466
467 switch (data->center) {
468 case VIK_PRINT_CENTER_NONE:
469 if (data->offset_x > offset_x_max)
470 data->offset_x = offset_x_max;
471 if (data->offset_y > offset_y_max)
472 data->offset_y = offset_y_max;
473 break;
474
475 case VIK_PRINT_CENTER_HORIZONTALLY:
476 data->offset_x = offset_x_max / 2.0;
477 break;
478
479 case VIK_PRINT_CENTER_VERTICALLY:
480 data->offset_y = offset_y_max / 2.0;
481 break;
482
483 case VIK_PRINT_CENTER_BOTH:
484 data->offset_x = offset_x_max / 2.0;
485 data->offset_y = offset_y_max / 2.0;
486 break;
9351abc4
RN
487
488 default: break;
489 }
42f34743
QT
490}
491
492static void center_changed_cb (GtkWidget *combo, CustomWidgetInfo *info)
493{
494 info->data->center = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
495 update_offsets (info);
496
497 if (info->preview)
498 vik_print_preview_set_image_offsets (VIK_PRINT_PREVIEW (info->preview),
499 info->data->offset_x, info->data->offset_y);
500}
501
502static gboolean scale_change_value_cb(GtkRange *range,
503 GtkScrollType scroll,
504 gdouble value,
505 CustomWidgetInfo *pinfo)
506{
507 gdouble paper_width;
508 gdouble paper_height;
509 gdouble xres, yres, res;
510 gdouble offset_x_max, offset_y_max;
511 gdouble scale = CLAMP(value, 1, 100);
512
513 get_page_dimensions (pinfo, &paper_width, &paper_height, GTK_UNIT_INCH);
514 xres = pinfo->data->width * 100 / paper_width / scale;
515 yres = pinfo->data->height * 100 / paper_height / scale;
516 res = MAX(xres, yres);
517 pinfo->data->xres = pinfo->data->yres = res;
518 get_max_offsets (pinfo, &offset_x_max, &offset_y_max);
519 update_offsets (pinfo);
520 if (pinfo->preview) {
521 vik_print_preview_set_image_dpi (VIK_PRINT_PREVIEW (pinfo->preview),
522 pinfo->data->xres, pinfo->data->yres);
523 vik_print_preview_set_image_offsets (VIK_PRINT_PREVIEW (pinfo->preview),
524 pinfo->data->offset_x, pinfo->data->offset_y);
525 vik_print_preview_set_image_offsets_max (VIK_PRINT_PREVIEW (pinfo->preview),
526 offset_x_max, offset_y_max);
527 }
528
529 set_scale_label(pinfo, scale);
530
531 return FALSE;
532}
533
534static void custom_widgets_cleanup(CustomWidgetInfo *info)
535{
536 g_free(info);
537}
538
539static GtkWidget *create_custom_widget_cb(GtkPrintOperation *operation, PrintData *data)
540{
541 GtkWidget *layout;
542 GtkWidget *main_hbox;
543 GtkWidget *main_vbox;
544 GtkWidget *hbox;
545 GtkWidget *vbox;
546 GtkWidget *button;
547 GtkWidget *label;
548 GtkPageSetup *setup;
549
550 CustomWidgetInfo *info = g_malloc0(sizeof(CustomWidgetInfo));
7760b0cf 551 g_signal_connect_swapped (data->operation, _("done"), G_CALLBACK (custom_widgets_cleanup), info);
42f34743
QT
552
553
554 info->data = data;
555
556 setup = gtk_print_operation_get_default_page_setup (data->operation);
557 if (! setup) {
558 setup = gtk_page_setup_new ();
559 gtk_print_operation_set_default_page_setup (data->operation, setup);
560 }
561
562 layout = gtk_vbox_new (FALSE, 6);
563 gtk_container_set_border_width (GTK_CONTAINER (layout), 12);
564
565 /* main hbox */
566 main_hbox = gtk_hbox_new (FALSE, 12);
567 gtk_box_pack_start (GTK_BOX (layout), main_hbox, TRUE, TRUE, 0);
568 gtk_widget_show (main_hbox);
569
570 /* main vbox */
571 main_vbox = gtk_vbox_new (FALSE, 12);
572 gtk_box_pack_start (GTK_BOX (main_hbox), main_vbox, FALSE, FALSE, 0);
573 gtk_widget_show (main_vbox);
574
575 vbox = gtk_vbox_new (FALSE, 6);
576 gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0);
577 gtk_widget_show (vbox);
578
579 /* Page Size */
7760b0cf
JJ
580 button = gtk_button_new_with_mnemonic (_("_Adjust Page Size "
581 "and Orientation"));
42f34743
QT
582 gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0);
583 g_signal_connect (G_OBJECT (button), "clicked",
584 G_CALLBACK (page_setup_cb),
585 info);
586 gtk_widget_show (button);
587
588 /* Center */
589 GtkWidget *combo;
590 const PrintCenterName *center;
591
592 hbox = gtk_hbox_new (FALSE, 6);
593 gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
594 gtk_widget_show (hbox);
595
7760b0cf 596 label = gtk_label_new_with_mnemonic (_("C_enter:"));
42f34743
QT
597 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
598 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
599 gtk_widget_show (label);
600
1bc1c05b 601 combo = vik_combo_box_text_new ();
42f34743 602 for (center = center_modes; center->name; center++) {
1bc1c05b 603 vik_combo_box_text_append (combo, _(center->name));
42f34743
QT
604 }
605 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), VIK_PRINT_CENTER_BOTH);
606 gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
607 gtk_widget_show (combo);
608 gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
609 g_signal_connect(combo, "changed",
610 G_CALLBACK(center_changed_cb), info);
611 info->center_combo = combo;
612
613 /* ignore page margins */
7760b0cf 614 button = gtk_check_button_new_with_mnemonic (_("Ignore Page _Margins"));
42f34743
QT
615
616 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
617 data->use_full_page);
618 gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0);
619 g_signal_connect (button, "toggled",
620 G_CALLBACK (full_page_toggled_cb),
621 info);
622 gtk_widget_show (button);
623
624 /* scale */
625 vbox = gtk_vbox_new (FALSE, 1);
626 gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0);
627 gtk_widget_show (vbox);
628
629 hbox = gtk_hbox_new (FALSE, 6);
630 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
631 gtk_widget_show (hbox);
632
7760b0cf 633 label = gtk_label_new_with_mnemonic (_("Image S_ize:"));
42f34743
QT
634 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
635 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
636 gtk_widget_show (label);
637
638 label = gtk_label_new (NULL);
639 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
640 info->scale_label = label;
641 gtk_box_pack_start (GTK_BOX (hbox), info->scale_label, TRUE, TRUE, 0);
642 gtk_widget_show (info->scale_label);
643
644 info->scale = gtk_hscale_new_with_range(1, 100, 1);
645 gtk_box_pack_start (GTK_BOX (vbox), info->scale, TRUE, TRUE, 0);
646 gtk_scale_set_draw_value(GTK_SCALE(info->scale), FALSE);
647 gtk_widget_show (info->scale);
648 gtk_label_set_mnemonic_widget (GTK_LABEL (label), info->scale);
649
650 g_signal_connect(info->scale, "change_value",
651 G_CALLBACK(scale_change_value_cb), info);
652
653
654 info->preview = vik_print_preview_new (setup, GDK_DRAWABLE(vik_viewport_get_pixmap(data->vvp)));
655 vik_print_preview_set_use_full_page (VIK_PRINT_PREVIEW(info->preview),
656 data->use_full_page);
657 gtk_box_pack_start (GTK_BOX (main_hbox), info->preview, TRUE, TRUE, 0);
658 gtk_widget_show (info->preview);
659
660 g_signal_connect (info->preview, "offsets-changed",
661 G_CALLBACK (preview_offsets_changed_cb),
662 info);
663
664 update_page_setup (info);
665
666 gdouble offset_x_max, offset_y_max;
667 get_max_offsets (info, &offset_x_max, &offset_y_max);
668 vik_print_preview_set_image_offsets_max (VIK_PRINT_PREVIEW (info->preview),
669 offset_x_max, offset_y_max);
670
671 set_scale_value(info);
672
673 return layout;
674}