Add a unit test for VikGotoXmlTool
[viking/guyou.git] / src / print.c
blobc6f838962d4a3fa95ea46b0e53334fef46192db6
1 /*
2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
6 * print.c
7 * Copyright (C) 2007, Quy Tonthat <qtonthat@gmail.com>
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.
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.
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
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
28 #include <string.h>
29 #include <glib/gprintf.h>
30 #include <glib/gi18n.h>
31 #include <gtk/gtk.h>
33 #if GTK_CHECK_VERSION(2,10,0)
35 #include "viking.h"
36 #include "print.h"
37 #include "print-preview.h"
39 typedef enum
41 VIK_PRINT_CENTER_NONE = 0,
42 VIK_PRINT_CENTER_HORIZONTALLY,
43 VIK_PRINT_CENTER_VERTICALLY,
44 VIK_PRINT_CENTER_BOTH,
45 } PrintCenterMode;
47 typedef struct {
48 gchar *name;
49 PrintCenterMode mode;
50 } PrintCenterName;
52 static const PrintCenterName center_modes[] = {
53 {N_("None"), VIK_PRINT_CENTER_NONE},
54 {N_("Horizontally"), VIK_PRINT_CENTER_HORIZONTALLY},
55 {N_("Vertically"), VIK_PRINT_CENTER_VERTICALLY},
56 {N_("Both"), VIK_PRINT_CENTER_BOTH},
57 {NULL, -1}
60 typedef struct {
61 gint num_pages;
62 gboolean show_info_header;
63 VikWindow *vw;
64 VikViewport *vvp;
65 gdouble xmpp, ympp; /* zoom level (meters/pixel) */
66 gdouble xres;
67 gdouble yres;
68 gint width;
69 gint height;
70 gdouble offset_x;
71 gdouble offset_y;
72 PrintCenterMode center;
73 gboolean use_full_page;
74 GtkPrintOperation *operation;
75 } PrintData;
77 static GtkWidget *create_custom_widget_cb(GtkPrintOperation *operation, PrintData *data);
78 static void begin_print(GtkPrintOperation *operation, GtkPrintContext *context, PrintData *data);
79 static void draw_page(GtkPrintOperation *print, GtkPrintContext *context, gint page_nr, PrintData *data);
80 static void end_print(GtkPrintOperation *operation, GtkPrintContext *context, PrintData *data);
82 void a_print(VikWindow *vw, VikViewport *vvp)
84 /* TODO: make print_settings non-static when saving_settings_to_file is
85 * implemented. Keep it static for now to retain settings for each
86 * viking session
88 static GtkPrintSettings *print_settings = NULL;
90 GtkPrintOperation *print_oper;
91 GtkPrintOperationResult res;
92 PrintData data;
94 print_oper = gtk_print_operation_new ();
96 data.num_pages = 1;
97 data.vw = vw;
98 data.vvp = vvp;
99 data.offset_x = 0;
100 data.offset_y = 0;
101 data.center = VIK_PRINT_CENTER_BOTH;
102 data.use_full_page = FALSE;
103 data.operation = print_oper;
105 data.xmpp = vik_viewport_get_xmpp(vvp);
106 data.ympp = vik_viewport_get_ympp(vvp);
107 data.width = vik_viewport_get_width(vvp);
108 data.height = vik_viewport_get_height(vvp);
110 data.xres = data.yres = 230; /* FIXME */
112 if (print_settings != NULL)
113 gtk_print_operation_set_print_settings (print_oper, print_settings);
115 g_signal_connect (print_oper, "begin_print", G_CALLBACK (begin_print), &data);
116 g_signal_connect (print_oper, "draw_page", G_CALLBACK (draw_page), &data);
117 g_signal_connect (print_oper, "end-print", G_CALLBACK (end_print), &data);
118 g_signal_connect (print_oper, "create-custom-widget", G_CALLBACK (create_custom_widget_cb), &data);
120 gtk_print_operation_set_custom_tab_label (print_oper, _("Image Settings"));
122 res = gtk_print_operation_run (print_oper,
123 GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
124 GTK_WINDOW (vw), NULL);
126 if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
127 if (print_settings != NULL)
128 g_object_unref (print_settings);
129 print_settings = g_object_ref (gtk_print_operation_get_print_settings (print_oper));
132 g_object_unref (print_oper);
135 static void begin_print(GtkPrintOperation *operation,
136 GtkPrintContext *context,
137 PrintData *data)
139 // fputs("DEBUG: begin_print() called\n", stderr);
140 gtk_print_operation_set_n_pages (operation, data->num_pages);
141 gtk_print_operation_set_use_full_page (operation, data->use_full_page);
145 static void end_print(GtkPrintOperation *operation,
146 GtkPrintContext *context,
147 PrintData *data)
149 // fputs("DEBUG: end_print() called\n", stderr);
153 static void copy_row_from_rgb(guchar *surface_pixels, guchar *pixbuf_pixels, gint width)
155 guint32 *cairo_data = (guint32 *) surface_pixels;
156 guchar *p;
157 gint i;
159 for (i = 0, p = pixbuf_pixels; i < width; i++) {
160 guint32 r = *p++;
161 guint32 g = *p++;
162 guint32 b = *p++;
163 cairo_data[i] = 0xFF000000 | (r << 16) | (g << 8) | b;
167 #define INT_MULT(a,b,t) ((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8))
168 #define INT_BLEND(a,b,alpha,tmp) (INT_MULT((a) - (b), alpha, tmp) + (b))
169 static void copy_row_from_rgba(guchar *surface_pixels, guchar *pixbuf_pixels, gint width)
171 guint32 *cairo_data = (guint32 *) surface_pixels;
172 guchar *p;
173 gint i;
175 for (i = 0, p = pixbuf_pixels; i < width; i++) {
176 guint32 r = *p++;
177 guint32 g = *p++;
178 guint32 b = *p++;
179 guint32 a = *p++;
181 if (a != 255) {
182 guint32 tmp;
183 /* composite on a white background */
184 r = INT_BLEND (r, 255, a, tmp);
185 g = INT_BLEND (g, 255, a, tmp);
186 b = INT_BLEND (b, 255, a, tmp);
188 cairo_data[i] = 0xFF000000 | (r << 16) | (g << 8) | b;
192 static void draw_page_cairo(GtkPrintContext *context, PrintData *data)
194 cairo_t *cr;
195 GdkPixbuf *pixbuf_to_draw;
196 cairo_surface_t *surface;
197 guchar *surface_pixels;
198 guchar *pixbuf_pixels;
199 gint stride;
200 gint pixbuf_stride;
201 gint pixbuf_n_channels;
202 gdouble cr_width;
203 gdouble cr_height;
204 gdouble cr_dpi_x;
205 gdouble cr_dpi_y;
206 gdouble scale_x;
207 gdouble scale_y;
208 gint y;
210 cr = gtk_print_context_get_cairo_context(context);
211 pixbuf_to_draw = gdk_pixbuf_get_from_drawable(NULL,
212 GDK_DRAWABLE(vik_viewport_get_pixmap(data->vvp)),
213 NULL, 0, 0, 0, 0, data->width, data->height);
214 surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
215 data->width, data->height);
217 cr_width = gtk_print_context_get_width (context);
218 cr_height = gtk_print_context_get_height (context);
219 cr_dpi_x = gtk_print_context_get_dpi_x (context);
220 cr_dpi_y = gtk_print_context_get_dpi_y (context);
222 scale_x = cr_dpi_x / data->xres;
223 scale_y = cr_dpi_y / data->yres;
225 cairo_translate (cr,
226 data->offset_x / cr_dpi_x * 72.0,
227 data->offset_y / cr_dpi_y * 72.0);
228 cairo_scale (cr, scale_x, scale_y);
230 surface_pixels = cairo_image_surface_get_data (surface);
231 stride = cairo_image_surface_get_stride (surface);
232 pixbuf_pixels = gdk_pixbuf_get_pixels (pixbuf_to_draw);
233 pixbuf_stride = gdk_pixbuf_get_rowstride(pixbuf_to_draw);
234 pixbuf_n_channels = gdk_pixbuf_get_n_channels(pixbuf_to_draw);
236 // 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));
238 /* Assume the pixbuf has 8 bits per channel */
239 for (y = 0; y < data->height; y++, surface_pixels += stride, pixbuf_pixels += pixbuf_stride) {
240 switch (pixbuf_n_channels) {
241 case 3:
242 copy_row_from_rgb (surface_pixels, pixbuf_pixels, data->width);
243 break;
244 case 4:
245 copy_row_from_rgba (surface_pixels, pixbuf_pixels, data->width);
246 break;
250 g_object_unref(G_OBJECT(pixbuf_to_draw));
252 cairo_set_source_surface(cr, surface, 0, 0);
253 cairo_rectangle(cr, 0, 0, data->width, data->height);
254 cairo_fill(cr);
255 cairo_surface_destroy(surface);
258 static void draw_page(GtkPrintOperation *print,
259 GtkPrintContext *context,
260 gint page_nr,
261 PrintData *data)
263 // fprintf(stderr, "DEBUG: draw_page() page_nr=%d\n", page_nr);
264 draw_page_cairo(context, data);
268 /*********************** page layout gui *********************/
269 typedef struct
271 PrintData *data;
272 GtkWidget *center_combo;
273 GtkWidget *scale;
274 GtkWidget *scale_label;
275 GtkWidget *preview;
276 } CustomWidgetInfo;
278 enum
280 BOTTOM,
281 TOP,
282 RIGHT,
283 LEFT,
284 WIDTH,
285 HEIGHT
288 static gboolean scale_change_value_cb(GtkRange *range, GtkScrollType scroll, gdouble value, CustomWidgetInfo *pinfo);
289 static void get_page_dimensions (CustomWidgetInfo *info, gdouble *page_width, gdouble *page_height, GtkUnit unit);
290 static void center_changed_cb (GtkWidget *combo, CustomWidgetInfo *info);
291 static void get_max_offsets (CustomWidgetInfo *info, gdouble *offset_x_max, gdouble *offset_y_max);
292 static void update_offsets (CustomWidgetInfo *info);
294 static void set_scale_label(CustomWidgetInfo *pinfo, gdouble scale_val)
296 static const gdouble inch_to_mm = 25.4;
297 gchar label_text[64];
299 g_snprintf(label_text, sizeof(label_text), "<i>%.0fx%0.f mm (%.0f%%)</i>",
300 inch_to_mm * pinfo->data->width / pinfo->data->xres,
301 inch_to_mm * pinfo->data->height / pinfo->data->yres,
302 scale_val);
303 gtk_label_set_markup (GTK_LABEL (pinfo->scale_label), label_text);
306 static void set_scale_value(CustomWidgetInfo *pinfo)
308 gdouble width;
309 gdouble height;
310 gdouble ratio, ratio_w, ratio_h;
313 get_page_dimensions (pinfo, &width, &height, GTK_UNIT_INCH);
314 ratio_w = 100 * pinfo->data->width / pinfo->data->xres / width;
315 ratio_h = 100 * pinfo->data->height / pinfo->data->yres / height;
317 ratio = MAX(ratio_w, ratio_h);
318 g_signal_handlers_block_by_func(GTK_RANGE(pinfo->scale), scale_change_value_cb, pinfo);
319 gtk_range_set_value(GTK_RANGE(pinfo->scale), ratio);
320 g_signal_handlers_unblock_by_func(GTK_RANGE(pinfo->scale), scale_change_value_cb, pinfo);
321 set_scale_label(pinfo, ratio);
324 static void update_page_setup (CustomWidgetInfo *pinfo)
326 gdouble paper_width;
327 gdouble paper_height;
328 gdouble offset_x_max, offset_y_max;
329 PrintData *data = pinfo->data;
331 get_page_dimensions (pinfo, &paper_width, &paper_height, GTK_UNIT_INCH);
332 if ((paper_width < (pinfo->data->width / data->xres)) ||
333 (paper_height < (pinfo->data->height / data->yres))) {
334 gdouble xres, yres;
335 xres = (gdouble) pinfo->data->width / paper_width;
336 yres = (gdouble) pinfo->data->height / paper_height;
337 data->xres = data->yres = MAX(xres, yres);
338 vik_print_preview_set_image_dpi (VIK_PRINT_PREVIEW (pinfo->preview),
339 data->xres, data->yres);
341 get_max_offsets (pinfo, &offset_x_max, &offset_y_max);
342 vik_print_preview_set_image_offsets_max (VIK_PRINT_PREVIEW (pinfo->preview),
343 offset_x_max, offset_y_max);
344 update_offsets (pinfo);
345 set_scale_value(pinfo);
346 if (pinfo->preview)
347 vik_print_preview_set_image_offsets (VIK_PRINT_PREVIEW (pinfo->preview),
348 pinfo->data->offset_x, pinfo->data->offset_y);
352 static void page_setup_cb (GtkWidget *widget, CustomWidgetInfo *info)
354 PrintData *data = info->data;
355 GtkPrintOperation *operation = data->operation;
356 GtkPrintSettings *settings;
357 GtkPageSetup *page_setup;
358 GtkWidget *toplevel;
360 toplevel = gtk_widget_get_toplevel (widget);
361 if (! GTK_WIDGET_TOPLEVEL (toplevel))
362 toplevel = NULL;
364 settings = gtk_print_operation_get_print_settings (operation);
365 if (! settings)
366 settings = gtk_print_settings_new ();
368 page_setup = gtk_print_operation_get_default_page_setup (operation);
370 page_setup = gtk_print_run_page_setup_dialog (GTK_WINDOW (toplevel),
371 page_setup, settings);
373 gtk_print_operation_set_default_page_setup (operation, page_setup);
375 vik_print_preview_set_page_setup (VIK_PRINT_PREVIEW (info->preview),
376 page_setup);
378 update_page_setup (info);
382 static void full_page_toggled_cb (GtkWidget *widget, CustomWidgetInfo *pinfo)
384 gboolean active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
386 pinfo->data->use_full_page = active;
387 update_page_setup (pinfo);
388 vik_print_preview_set_use_full_page (VIK_PRINT_PREVIEW(pinfo->preview),
389 active);
392 static void set_center_none (CustomWidgetInfo *info)
394 info->data->center = VIK_PRINT_CENTER_NONE;
396 if (info->center_combo) {
397 g_signal_handlers_block_by_func (info->center_combo,
398 center_changed_cb, info);
400 info->data->center = VIK_PRINT_CENTER_NONE;
401 gtk_combo_box_set_active(GTK_COMBO_BOX(info->center_combo), info->data->center);
402 g_signal_handlers_unblock_by_func (info->center_combo,
403 center_changed_cb, info);
407 static void preview_offsets_changed_cb (GtkWidget *widget,
408 gdouble offset_x, gdouble offset_y,
409 CustomWidgetInfo *info)
411 set_center_none (info);
413 info->data->offset_x = offset_x;
414 info->data->offset_y = offset_y;
416 update_offsets (info);
420 static void get_page_dimensions (CustomWidgetInfo *info,
421 gdouble *page_width,
422 gdouble *page_height,
423 GtkUnit unit)
425 GtkPageSetup *setup;
427 setup = gtk_print_operation_get_default_page_setup (info->data->operation);
429 *page_width = gtk_page_setup_get_paper_width (setup, unit);
430 *page_height = gtk_page_setup_get_paper_height (setup, unit);
432 if (!info->data->use_full_page) {
433 gdouble left_margin = gtk_page_setup_get_left_margin (setup, unit);
434 gdouble right_margin = gtk_page_setup_get_right_margin (setup, unit);
435 gdouble top_margin = gtk_page_setup_get_top_margin (setup, unit);
436 gdouble bottom_margin = gtk_page_setup_get_bottom_margin (setup, unit);
438 *page_width -= left_margin + right_margin;
439 *page_height -= top_margin + bottom_margin;
444 static void get_max_offsets (CustomWidgetInfo *info,
445 gdouble *offset_x_max,
446 gdouble *offset_y_max)
448 gdouble width;
449 gdouble height;
451 get_page_dimensions (info, &width, &height, GTK_UNIT_POINTS);
453 *offset_x_max = width - 72.0 * info->data->width / info->data->xres;
454 *offset_x_max = MAX (0, *offset_x_max);
456 *offset_y_max = height - 72.0 * info->data->height / info->data->yres;
457 *offset_y_max = MAX (0, *offset_y_max);
460 static void update_offsets (CustomWidgetInfo *info)
462 PrintData *data = info->data;
463 gdouble offset_x_max;
464 gdouble offset_y_max;
466 get_max_offsets (info, &offset_x_max, &offset_y_max);
468 switch (data->center) {
469 case VIK_PRINT_CENTER_NONE:
470 if (data->offset_x > offset_x_max)
471 data->offset_x = offset_x_max;
472 if (data->offset_y > offset_y_max)
473 data->offset_y = offset_y_max;
474 break;
476 case VIK_PRINT_CENTER_HORIZONTALLY:
477 data->offset_x = offset_x_max / 2.0;
478 break;
480 case VIK_PRINT_CENTER_VERTICALLY:
481 data->offset_y = offset_y_max / 2.0;
482 break;
484 case VIK_PRINT_CENTER_BOTH:
485 data->offset_x = offset_x_max / 2.0;
486 data->offset_y = offset_y_max / 2.0;
487 break;
491 static void center_changed_cb (GtkWidget *combo, CustomWidgetInfo *info)
493 info->data->center = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
494 update_offsets (info);
496 if (info->preview)
497 vik_print_preview_set_image_offsets (VIK_PRINT_PREVIEW (info->preview),
498 info->data->offset_x, info->data->offset_y);
501 static gboolean scale_change_value_cb(GtkRange *range,
502 GtkScrollType scroll,
503 gdouble value,
504 CustomWidgetInfo *pinfo)
506 gdouble paper_width;
507 gdouble paper_height;
508 gdouble xres, yres, res;
509 gdouble offset_x_max, offset_y_max;
510 gdouble scale = CLAMP(value, 1, 100);
512 get_page_dimensions (pinfo, &paper_width, &paper_height, GTK_UNIT_INCH);
513 xres = pinfo->data->width * 100 / paper_width / scale;
514 yres = pinfo->data->height * 100 / paper_height / scale;
515 res = MAX(xres, yres);
516 pinfo->data->xres = pinfo->data->yres = res;
517 get_max_offsets (pinfo, &offset_x_max, &offset_y_max);
518 update_offsets (pinfo);
519 if (pinfo->preview) {
520 vik_print_preview_set_image_dpi (VIK_PRINT_PREVIEW (pinfo->preview),
521 pinfo->data->xres, pinfo->data->yres);
522 vik_print_preview_set_image_offsets (VIK_PRINT_PREVIEW (pinfo->preview),
523 pinfo->data->offset_x, pinfo->data->offset_y);
524 vik_print_preview_set_image_offsets_max (VIK_PRINT_PREVIEW (pinfo->preview),
525 offset_x_max, offset_y_max);
528 set_scale_label(pinfo, scale);
530 return FALSE;
533 static void custom_widgets_cleanup(CustomWidgetInfo *info)
535 g_free(info);
538 static GtkWidget *create_custom_widget_cb(GtkPrintOperation *operation, PrintData *data)
540 GtkWidget *layout;
541 GtkWidget *main_hbox;
542 GtkWidget *main_vbox;
543 GtkWidget *hbox;
544 GtkWidget *vbox;
545 GtkWidget *button;
546 GtkWidget *label;
547 GtkPageSetup *setup;
549 CustomWidgetInfo *info = g_malloc0(sizeof(CustomWidgetInfo));
550 g_signal_connect_swapped (data->operation, _("done"), G_CALLBACK (custom_widgets_cleanup), info);
553 info->data = data;
555 setup = gtk_print_operation_get_default_page_setup (data->operation);
556 if (! setup) {
557 setup = gtk_page_setup_new ();
558 gtk_print_operation_set_default_page_setup (data->operation, setup);
561 layout = gtk_vbox_new (FALSE, 6);
562 gtk_container_set_border_width (GTK_CONTAINER (layout), 12);
564 /* main hbox */
565 main_hbox = gtk_hbox_new (FALSE, 12);
566 gtk_box_pack_start (GTK_BOX (layout), main_hbox, TRUE, TRUE, 0);
567 gtk_widget_show (main_hbox);
569 /* main vbox */
570 main_vbox = gtk_vbox_new (FALSE, 12);
571 gtk_box_pack_start (GTK_BOX (main_hbox), main_vbox, FALSE, FALSE, 0);
572 gtk_widget_show (main_vbox);
574 vbox = gtk_vbox_new (FALSE, 6);
575 gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0);
576 gtk_widget_show (vbox);
578 /* Page Size */
579 button = gtk_button_new_with_mnemonic (_("_Adjust Page Size "
580 "and Orientation"));
581 gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0);
582 g_signal_connect (G_OBJECT (button), "clicked",
583 G_CALLBACK (page_setup_cb),
584 info);
585 gtk_widget_show (button);
587 /* Center */
588 GtkWidget *combo;
589 const PrintCenterName *center;
591 hbox = gtk_hbox_new (FALSE, 6);
592 gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
593 gtk_widget_show (hbox);
595 label = gtk_label_new_with_mnemonic (_("C_enter:"));
596 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
597 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
598 gtk_widget_show (label);
600 combo = gtk_combo_box_new_text ();
601 for (center = center_modes; center->name; center++) {
602 gtk_combo_box_append_text(GTK_COMBO_BOX(combo), _(center->name));
604 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), VIK_PRINT_CENTER_BOTH);
605 gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
606 gtk_widget_show (combo);
607 gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
608 g_signal_connect(combo, "changed",
609 G_CALLBACK(center_changed_cb), info);
610 info->center_combo = combo;
612 /* ignore page margins */
613 button = gtk_check_button_new_with_mnemonic (_("Ignore Page _Margins"));
615 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
616 data->use_full_page);
617 gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0);
618 g_signal_connect (button, "toggled",
619 G_CALLBACK (full_page_toggled_cb),
620 info);
621 gtk_widget_show (button);
623 /* scale */
624 vbox = gtk_vbox_new (FALSE, 1);
625 gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0);
626 gtk_widget_show (vbox);
628 hbox = gtk_hbox_new (FALSE, 6);
629 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
630 gtk_widget_show (hbox);
632 label = gtk_label_new_with_mnemonic (_("Image S_ize:"));
633 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
634 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
635 gtk_widget_show (label);
637 label = gtk_label_new (NULL);
638 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
639 info->scale_label = label;
640 gtk_box_pack_start (GTK_BOX (hbox), info->scale_label, TRUE, TRUE, 0);
641 gtk_widget_show (info->scale_label);
643 info->scale = gtk_hscale_new_with_range(1, 100, 1);
644 gtk_box_pack_start (GTK_BOX (vbox), info->scale, TRUE, TRUE, 0);
645 gtk_scale_set_draw_value(GTK_SCALE(info->scale), FALSE);
646 gtk_widget_show (info->scale);
647 gtk_label_set_mnemonic_widget (GTK_LABEL (label), info->scale);
649 g_signal_connect(info->scale, "change_value",
650 G_CALLBACK(scale_change_value_cb), info);
653 info->preview = vik_print_preview_new (setup, GDK_DRAWABLE(vik_viewport_get_pixmap(data->vvp)));
654 vik_print_preview_set_use_full_page (VIK_PRINT_PREVIEW(info->preview),
655 data->use_full_page);
656 gtk_box_pack_start (GTK_BOX (main_hbox), info->preview, TRUE, TRUE, 0);
657 gtk_widget_show (info->preview);
659 g_signal_connect (info->preview, "offsets-changed",
660 G_CALLBACK (preview_offsets_changed_cb),
661 info);
663 update_page_setup (info);
665 gdouble offset_x_max, offset_y_max;
666 get_max_offsets (info, &offset_x_max, &offset_y_max);
667 vik_print_preview_set_image_offsets_max (VIK_PRINT_PREVIEW (info->preview),
668 offset_x_max, offset_y_max);
670 set_scale_value(info);
672 return layout;
675 #endif