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