]> Pileus Git - ~andy/gtk/blob - demos/gtk-demo/printing.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / demos / gtk-demo / printing.c
1 /* Printing
2  *
3  * GtkPrintOperation offers a simple API to support printing
4  * in a cross-platform way.
5  *
6  */
7
8 #include <math.h>
9 #include <gtk/gtk.h>
10
11 /* In points */
12 #define HEADER_HEIGHT (10*72/25.4)
13 #define HEADER_GAP (3*72/25.4)
14
15 typedef struct
16 {
17   gchar *resourcename;
18   gdouble font_size;
19
20   gint lines_per_page;
21   gchar **lines;
22   gint num_lines;
23   gint num_pages;
24 } PrintData;
25
26 static void
27 begin_print (GtkPrintOperation *operation,
28              GtkPrintContext   *context,
29              gpointer           user_data)
30 {
31   PrintData *data = (PrintData *)user_data;
32   GBytes *bytes;
33   int i;
34   double height;
35
36   height = gtk_print_context_get_height (context) - HEADER_HEIGHT - HEADER_GAP;
37
38   data->lines_per_page = floor (height / data->font_size);
39
40   bytes = g_resources_lookup_data (data->resourcename, 0, NULL);
41
42   data->lines = g_strsplit (g_bytes_get_data (bytes, NULL), "\n", 0);
43   g_bytes_unref (bytes);
44
45   i = 0;
46   while (data->lines[i] != NULL)
47     i++;
48
49   data->num_lines = i;
50   data->num_pages = (data->num_lines - 1) / data->lines_per_page + 1;
51
52   gtk_print_operation_set_n_pages (operation, data->num_pages);
53 }
54
55 static void
56 draw_page (GtkPrintOperation *operation,
57            GtkPrintContext   *context,
58            gint               page_nr,
59            gpointer           user_data)
60 {
61   PrintData *data = (PrintData *)user_data;
62   cairo_t *cr;
63   PangoLayout *layout;
64   gint text_width, text_height;
65   gdouble width;
66   gint line, i;
67   PangoFontDescription *desc;
68   gchar *page_str;
69
70   cr = gtk_print_context_get_cairo_context (context);
71   width = gtk_print_context_get_width (context);
72
73   cairo_rectangle (cr, 0, 0, width, HEADER_HEIGHT);
74
75   cairo_set_source_rgb (cr, 0.8, 0.8, 0.8);
76   cairo_fill_preserve (cr);
77
78   cairo_set_source_rgb (cr, 0, 0, 0);
79   cairo_set_line_width (cr, 1);
80   cairo_stroke (cr);
81
82   layout = gtk_print_context_create_pango_layout (context);
83
84   desc = pango_font_description_from_string ("sans 14");
85   pango_layout_set_font_description (layout, desc);
86   pango_font_description_free (desc);
87
88   pango_layout_set_text (layout, data->resourcename, -1);
89   pango_layout_get_pixel_size (layout, &text_width, &text_height);
90
91   if (text_width > width)
92     {
93       pango_layout_set_width (layout, width);
94       pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_START);
95       pango_layout_get_pixel_size (layout, &text_width, &text_height);
96     }
97
98   cairo_move_to (cr, (width - text_width) / 2,  (HEADER_HEIGHT - text_height) / 2);
99   pango_cairo_show_layout (cr, layout);
100
101   page_str = g_strdup_printf ("%d/%d", page_nr + 1, data->num_pages);
102   pango_layout_set_text (layout, page_str, -1);
103   g_free (page_str);
104
105   pango_layout_set_width (layout, -1);
106   pango_layout_get_pixel_size (layout, &text_width, &text_height);
107   cairo_move_to (cr, width - text_width - 4, (HEADER_HEIGHT - text_height) / 2);
108   pango_cairo_show_layout (cr, layout);
109
110   g_object_unref (layout);
111
112   layout = gtk_print_context_create_pango_layout (context);
113
114   desc = pango_font_description_from_string ("monospace");
115   pango_font_description_set_size (desc, data->font_size * PANGO_SCALE);
116   pango_layout_set_font_description (layout, desc);
117   pango_font_description_free (desc);
118
119   cairo_move_to (cr, 0, HEADER_HEIGHT + HEADER_GAP);
120   line = page_nr * data->lines_per_page;
121   for (i = 0; i < data->lines_per_page && line < data->num_lines; i++)
122     {
123       pango_layout_set_text (layout, data->lines[line], -1);
124       pango_cairo_show_layout (cr, layout);
125       cairo_rel_move_to (cr, 0, data->font_size);
126       line++;
127     }
128
129   g_object_unref (layout);
130 }
131
132 static void
133 end_print (GtkPrintOperation *operation,
134            GtkPrintContext   *context,
135            gpointer           user_data)
136 {
137   PrintData *data = (PrintData *)user_data;
138
139   g_free (data->resourcename);
140   g_strfreev (data->lines);
141   g_free (data);
142 }
143
144
145 GtkWidget *
146 do_printing (GtkWidget *do_widget)
147 {
148   GtkPrintOperation *operation;
149   GtkPrintSettings *settings;
150   PrintData *data;
151   GError *error = NULL;
152
153   operation = gtk_print_operation_new ();
154   data = g_new0 (PrintData, 1);
155   data->resourcename = g_strdup ("/sources/printing.c");
156   data->font_size = 12.0;
157
158   g_signal_connect (G_OBJECT (operation), "begin-print",
159                     G_CALLBACK (begin_print), data);
160   g_signal_connect (G_OBJECT (operation), "draw-page",
161                     G_CALLBACK (draw_page), data);
162   g_signal_connect (G_OBJECT (operation), "end-print",
163                     G_CALLBACK (end_print), data);
164
165   gtk_print_operation_set_use_full_page (operation, FALSE);
166   gtk_print_operation_set_unit (operation, GTK_UNIT_POINTS);
167   gtk_print_operation_set_embed_page_setup (operation, TRUE);
168
169   settings = gtk_print_settings_new ();
170
171   gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_BASENAME, "gtk-demo");
172   gtk_print_operation_set_print_settings (operation, settings);
173
174   gtk_print_operation_run (operation, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, GTK_WINDOW (do_widget), &error);
175
176   g_object_unref (operation);
177   g_object_unref (settings);
178
179   if (error)
180     {
181       GtkWidget *dialog;
182
183       dialog = gtk_message_dialog_new (GTK_WINDOW (do_widget),
184                                        GTK_DIALOG_DESTROY_WITH_PARENT,
185                                        GTK_MESSAGE_ERROR,
186                                        GTK_BUTTONS_CLOSE,
187                                        "%s", error->message);
188       g_error_free (error);
189
190       g_signal_connect (dialog, "response",
191                         G_CALLBACK (gtk_widget_destroy), NULL);
192
193       gtk_widget_show (dialog);
194     }
195
196
197   return NULL;
198 }