3 * Copyright (C) 2001-2009 Jim Evins <evins@snaught.com>.
5 * This file is part of gLabels.
7 * gLabels is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * gLabels is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with gLabels. If not, see <http://www.gnu.org/licenses/>.
23 #include "print-op-dialog.h"
25 #include <glib/gi18n.h>
26 #include <gtk/gtkbuilder.h>
30 #include <gtk/gtktogglebutton.h>
31 #include <gtk/gtkspinbutton.h>
33 #include "mini-preview.h"
37 #include "pixmaps/collate.xpm"
38 #include "pixmaps/nocollate.xpm"
43 #define MINI_PREVIEW_MIN_HEIGHT 175
44 #define MINI_PREVIEW_MIN_WIDTH 150
47 /*===========================================*/
48 /* Private data types */
49 /*===========================================*/
51 struct _glPrintOpDialogPrivate {
55 GtkWidget *simple_frame;
56 GtkWidget *simple_sheets_radio;
57 GtkWidget *simple_sheets_spin;
58 GtkWidget *simple_labels_radio;
59 GtkWidget *simple_first_spin;
60 GtkWidget *simple_last_spin;
62 GtkWidget *merge_frame;
63 GtkWidget *merge_first_spin;
64 GtkWidget *merge_copies_spin;
65 GtkWidget *merge_collate_check;
66 GtkWidget *merge_collate_image;
68 GtkWidget *outline_check;
69 GtkWidget *reverse_check;
70 GtkWidget *crop_marks_check;
74 gboolean force_outline_flag;
76 gint labels_per_sheet;
83 /*===========================================*/
85 /*===========================================*/
88 /*===========================================*/
89 /* Local function prototypes */
90 /*===========================================*/
92 static void gl_print_op_dialog_finalize (GObject *object);
94 static void gl_print_op_dialog_construct (glPrintOpDialog *op,
97 static GObject *create_custom_widget_cb (GtkPrintOperation *operation,
100 static void custom_widget_apply_cb (GtkPrintOperation *operation,
104 static void simple_sheets_radio_cb (GtkToggleButton *togglebutton,
105 glPrintOpDialog *op);
107 static void simple_first_spin_cb (GtkSpinButton *spinbutton,
108 glPrintOpDialog *op);
110 static void simple_last_spin_cb (GtkSpinButton *spinbutton,
111 glPrintOpDialog *op);
113 static void preview_pressed_cb (glMiniPreview *preview,
116 glPrintOpDialog *op);
118 static void merge_spin_cb (GtkSpinButton *spinbutton,
119 glPrintOpDialog *op);
121 static void merge_collate_check_cb (GtkToggleButton *togglebutton,
122 glPrintOpDialog *op);
124 static void preview_clicked_cb (glMiniPreview *preview,
126 glPrintOpDialog *op);
129 /*****************************************************************************/
130 /* Boilerplate object stuff. */
131 /*****************************************************************************/
132 G_DEFINE_TYPE (glPrintOpDialog, gl_print_op_dialog, GL_TYPE_PRINT_OP);
136 gl_print_op_dialog_class_init (glPrintOpDialogClass *class)
138 GObjectClass *object_class = G_OBJECT_CLASS (class);
140 gl_debug (DEBUG_PRINT, "");
142 gl_print_op_dialog_parent_class = g_type_class_peek_parent (class);
144 object_class->finalize = gl_print_op_dialog_finalize;
149 gl_print_op_dialog_init (glPrintOpDialog *op)
151 gl_debug (DEBUG_PRINT, "");
153 gtk_print_operation_set_use_full_page (GTK_PRINT_OPERATION (op), TRUE);
155 gtk_print_operation_set_unit (GTK_PRINT_OPERATION (op), GTK_UNIT_POINTS);
157 op->priv = g_new0 (glPrintOpDialogPrivate, 1);
163 gl_print_op_dialog_finalize (GObject *object)
165 glPrintOpDialog *op = GL_PRINT_OP_DIALOG (object);
167 gl_debug (DEBUG_PRINT, "");
169 g_return_if_fail (object != NULL);
170 g_return_if_fail (GL_IS_PRINT_OP (op));
171 g_return_if_fail (op->priv != NULL);
173 g_object_unref (G_OBJECT(op->priv->builder));
176 G_OBJECT_CLASS (gl_print_op_dialog_parent_class)->finalize (object);
182 /*****************************************************************************/
184 /*****************************************************************************/
186 gl_print_op_dialog_new (glLabel *label)
190 gl_debug (DEBUG_PRINT, "");
192 op = GL_PRINT_OP_DIALOG (g_object_new (GL_TYPE_PRINT_OP_DIALOG, NULL));
194 gl_print_op_dialog_construct (GL_PRINT_OP_DIALOG(op), label);
200 /*--------------------------------------------------------------------------*/
201 /* PRIVATE. Construct op. */
202 /*--------------------------------------------------------------------------*/
204 gl_print_op_dialog_construct (glPrintOpDialog *op,
208 gl_print_op_construct(GL_PRINT_OP (op), label);
210 gtk_print_operation_set_custom_tab_label ( GTK_PRINT_OPERATION (op),
213 g_signal_connect (G_OBJECT (op), "create-custom-widget",
214 G_CALLBACK (create_custom_widget_cb), label);
216 g_signal_connect (G_OBJECT (op), "custom-widget-apply",
217 G_CALLBACK (custom_widget_apply_cb), label);
222 /*--------------------------------------------------------------------------*/
223 /* PRIVATE. "Create custom widget" callback */
224 /*--------------------------------------------------------------------------*/
226 create_custom_widget_cb (GtkPrintOperation *operation,
230 static gchar *object_ids[] = { "print_custom_widget_hbox",
231 "adjustment1", "adjustment2",
232 "adjustment3", "adjustment4",
235 GError *error = NULL;
236 glPrintOpDialog *op = GL_PRINT_OP_DIALOG (operation);
237 const lglTemplateFrame *frame;
239 glMerge *merge = NULL;
243 frame = (lglTemplateFrame *)label->template->frames->data;
244 op->priv->labels_per_sheet = lgl_template_frame_get_n_labels (frame);
246 builder = gtk_builder_new ();
247 gtk_builder_add_objects_from_file (builder,
248 GLABELS_BUILDER_DIR "print-op-dialog-custom-widget.builder",
252 g_critical ("%s\n\ngLabels may not be installed correctly!", error->message);
253 g_error_free (error);
257 gl_util_get_builder_widgets (builder,
258 "print_custom_widget_hbox", &hbox,
259 "simple_frame", &op->priv->simple_frame,
260 "simple_sheets_radio", &op->priv->simple_sheets_radio,
261 "simple_sheets_spin", &op->priv->simple_sheets_spin,
262 "simple_labels_radio", &op->priv->simple_labels_radio,
263 "simple_first_spin", &op->priv->simple_first_spin,
264 "simple_last_spin", &op->priv->simple_last_spin,
265 "merge_frame", &op->priv->merge_frame,
266 "merge_first_spin", &op->priv->merge_first_spin,
267 "merge_copies_spin", &op->priv->merge_copies_spin,
268 "merge_collate_check", &op->priv->merge_collate_check,
269 "merge_collate_image", &op->priv->merge_collate_image,
270 "outline_check", &op->priv->outline_check,
271 "reverse_check", &op->priv->reverse_check,
272 "crop_marks_check", &op->priv->crop_marks_check,
275 op->priv->builder = builder;
277 /* ---- Install preview. ---- */
278 op->priv->preview = gl_mini_preview_new (MINI_PREVIEW_MIN_HEIGHT, MINI_PREVIEW_MIN_WIDTH);
279 gl_mini_preview_set_template (GL_MINI_PREVIEW(op->priv->preview), label->template);
280 gtk_box_pack_start (GTK_BOX(hbox), op->priv->preview, TRUE, TRUE, 0);
281 gtk_widget_show_all (op->priv->preview);
284 /* ---- Activate either simple or merge print control widgets. ---- */
285 merge = gl_label_get_merge (label);
286 op->priv->merge_flag = (merge != NULL);
287 if (!op->priv->merge_flag) {
289 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (op->priv->simple_sheets_radio),
291 gtk_widget_set_sensitive (op->priv->simple_first_spin, FALSE);
292 gtk_widget_set_sensitive (op->priv->simple_last_spin, FALSE);
294 gtk_spin_button_set_value (GTK_SPIN_BUTTON (op->priv->simple_sheets_spin),
295 gl_print_op_get_n_sheets (GL_PRINT_OP(op)));
297 gtk_spin_button_set_range (GTK_SPIN_BUTTON (op->priv->simple_first_spin),
298 1, op->priv->labels_per_sheet);
299 gtk_spin_button_set_value (GTK_SPIN_BUTTON (op->priv->simple_first_spin),
302 gtk_spin_button_set_range (GTK_SPIN_BUTTON (op->priv->simple_last_spin),
303 1, op->priv->labels_per_sheet);
304 gtk_spin_button_set_value (GTK_SPIN_BUTTON (op->priv->simple_last_spin),
305 op->priv->labels_per_sheet);
307 /* Update preview. */
308 gl_mini_preview_highlight_range (GL_MINI_PREVIEW (op->priv->preview),
309 1, op->priv->labels_per_sheet);
311 gtk_widget_show_all (op->priv->simple_frame);
312 gtk_widget_hide_all (op->priv->merge_frame);
314 g_signal_connect (G_OBJECT (op->priv->simple_sheets_radio), "toggled",
315 G_CALLBACK (simple_sheets_radio_cb), op);
316 g_signal_connect (G_OBJECT (op->priv->simple_first_spin), "changed",
317 G_CALLBACK (simple_first_spin_cb), op);
318 g_signal_connect (G_OBJECT (op->priv->simple_last_spin), "changed",
319 G_CALLBACK (simple_last_spin_cb), op);
320 g_signal_connect (G_OBJECT (op->priv->preview), "pressed",
321 G_CALLBACK (preview_pressed_cb), op);
325 op->priv->n_records = gl_merge_get_record_count (merge);
327 gtk_spin_button_set_range (GTK_SPIN_BUTTON (op->priv->merge_first_spin),
328 1, op->priv->labels_per_sheet);
329 gtk_spin_button_set_value (GTK_SPIN_BUTTON (op->priv->merge_first_spin),
330 gl_print_op_get_first (GL_PRINT_OP(op)));
332 gtk_spin_button_set_value (GTK_SPIN_BUTTON (op->priv->merge_copies_spin),
333 gl_print_op_get_n_copies (GL_PRINT_OP(op)));
335 gtk_widget_set_sensitive (op->priv->merge_collate_check,
336 (gl_print_op_get_n_copies (GL_PRINT_OP(op)) > 1));
337 gtk_widget_set_sensitive (op->priv->merge_collate_image,
338 (gl_print_op_get_n_copies (GL_PRINT_OP(op)) > 1));
341 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (op->priv->simple_sheets_radio),
342 gl_print_op_get_collate_flag (GL_PRINT_OP(op)));
344 if ( gl_print_op_get_collate_flag (GL_PRINT_OP(op)) )
346 pixbuf = gdk_pixbuf_new_from_xpm_data ( (const char **)collate_xpm);
350 pixbuf = gdk_pixbuf_new_from_xpm_data ( (const char **)nocollate_xpm);
353 gtk_image_set_from_pixbuf (GTK_IMAGE (op->priv->merge_collate_image), pixbuf);
355 /* Update preview. */
356 gl_mini_preview_highlight_range (GL_MINI_PREVIEW (op->priv->preview),
357 gl_print_op_get_first (GL_PRINT_OP(op)),
358 gl_print_op_get_first (GL_PRINT_OP(op)) + op->priv->n_records - 1);
360 gtk_widget_hide_all (op->priv->simple_frame);
361 gtk_widget_show_all (op->priv->merge_frame);
363 g_signal_connect (G_OBJECT (op->priv->merge_first_spin), "changed",
364 G_CALLBACK (merge_spin_cb), op);
365 g_signal_connect (G_OBJECT (op->priv->merge_copies_spin), "changed",
366 G_CALLBACK (merge_spin_cb), op);
367 g_signal_connect (G_OBJECT (op->priv->merge_collate_check), "toggled",
368 G_CALLBACK (merge_collate_check_cb), op);
369 g_signal_connect (G_OBJECT (op->priv->preview), "clicked",
370 G_CALLBACK (preview_clicked_cb), op);
372 g_object_unref (G_OBJECT(merge));
376 /* --- Set options --- */
377 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (op->priv->outline_check),
378 gl_print_op_get_outline_flag (GL_PRINT_OP(op)));
379 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (op->priv->reverse_check),
380 gl_print_op_get_reverse_flag (GL_PRINT_OP(op)));
381 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (op->priv->crop_marks_check),
382 gl_print_op_get_crop_marks_flag (GL_PRINT_OP(op)));
384 /* --- Do we need to force the outline flag --- */
385 if (gl_print_op_is_outline_forced (GL_PRINT_OP (op)))
387 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(op->priv->outline_check),
390 gtk_widget_set_sensitive (op->priv->outline_check, FALSE);
391 gtk_widget_set_sensitive (op->priv->reverse_check, FALSE);
392 gtk_widget_set_sensitive (op->priv->crop_marks_check, FALSE);
395 return G_OBJECT (hbox);
399 /*--------------------------------------------------------------------------*/
400 /* PRIVATE. "Custom widget apply" callback */
401 /*--------------------------------------------------------------------------*/
403 custom_widget_apply_cb (GtkPrintOperation *operation,
407 glPrintOpDialog *op = GL_PRINT_OP_DIALOG (operation);
408 glMerge *merge = NULL;
410 gint n_sheets, first, last, n_copies;
411 gboolean collate_flag;
413 gl_print_op_set_outline_flag (GL_PRINT_OP (op),
414 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
415 (op->priv->outline_check)));
416 gl_print_op_set_reverse_flag (GL_PRINT_OP (op),
417 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
418 (op->priv->reverse_check)));
419 gl_print_op_set_crop_marks_flag (GL_PRINT_OP (op),
420 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
421 (op->priv->crop_marks_check)));
424 if (!op->priv->merge_flag)
427 n_sheets = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (op->priv->simple_sheets_spin));
428 gl_print_op_set_n_sheets (GL_PRINT_OP (op), n_sheets);
430 first = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (op->priv->simple_first_spin));
431 gl_print_op_set_first (GL_PRINT_OP (op), first);
433 last = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (op->priv->simple_last_spin));
434 gl_print_op_set_last (GL_PRINT_OP (op), last);
440 merge = gl_label_get_merge (label);
442 n_copies = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (op->priv->merge_copies_spin));
443 gl_print_op_set_n_copies (GL_PRINT_OP (op), n_copies);
445 first = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (op->priv->merge_first_spin));
446 gl_print_op_set_first (GL_PRINT_OP (op), first);
448 collate_flag = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (op->priv->merge_collate_check));
449 gl_print_op_set_collate_flag (GL_PRINT_OP (op), collate_flag);
451 n_records = gl_merge_get_record_count (merge);
452 n_sheets = ceil (first - 1 + (n_copies * n_records)/(double)op->priv->labels_per_sheet);
453 gl_print_op_set_n_sheets (GL_PRINT_OP (op), n_sheets);
455 g_object_unref (G_OBJECT(merge));
463 /*--------------------------------------------------------------------------*/
464 /* PRIVATE. Simple sheets radio "toggled" callback */
465 /*--------------------------------------------------------------------------*/
467 simple_sheets_radio_cb (GtkToggleButton *togglebutton,
472 if (gtk_toggle_button_get_active (togglebutton)) {
474 gtk_widget_set_sensitive (op->priv->simple_sheets_spin, TRUE);
475 gtk_widget_set_sensitive (op->priv->simple_first_spin, FALSE);
476 gtk_widget_set_sensitive (op->priv->simple_last_spin, FALSE);
478 gtk_spin_button_set_range (GTK_SPIN_BUTTON (op->priv->simple_first_spin),
479 1, op->priv->labels_per_sheet);
480 gtk_spin_button_set_value (GTK_SPIN_BUTTON (op->priv->simple_first_spin),
483 gtk_spin_button_set_range (GTK_SPIN_BUTTON (op->priv->simple_last_spin),
484 1, op->priv->labels_per_sheet);
485 gtk_spin_button_set_value (GTK_SPIN_BUTTON (op->priv->simple_last_spin),
486 op->priv->labels_per_sheet);
488 gl_mini_preview_highlight_range (GL_MINI_PREVIEW (op->priv->preview),
489 1, op->priv->labels_per_sheet);
493 gtk_widget_set_sensitive (op->priv->simple_sheets_spin, FALSE);
494 gtk_widget_set_sensitive (op->priv->simple_first_spin, TRUE);
495 gtk_widget_set_sensitive (op->priv->simple_last_spin, TRUE);
497 gtk_spin_button_set_value (GTK_SPIN_BUTTON (op->priv->simple_sheets_spin), 1);
499 first = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (op->priv->simple_first_spin));
500 last = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (op->priv->simple_last_spin));
502 gl_mini_preview_highlight_range (GL_MINI_PREVIEW (op->priv->preview), first, last);
507 /*--------------------------------------------------------------------------*/
508 /* PRIVATE. Simple first label spinbutton "changed" callback */
509 /*--------------------------------------------------------------------------*/
511 simple_first_spin_cb (GtkSpinButton *spinbutton,
516 first = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (op->priv->simple_first_spin));
517 last = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (op->priv->simple_last_spin));
519 /* Adjust range of last spin button. */
520 gtk_spin_button_set_range (GTK_SPIN_BUTTON (op->priv->simple_last_spin),
521 first, op->priv->labels_per_sheet);
523 /* Update preview. */
524 gl_mini_preview_highlight_range (GL_MINI_PREVIEW (op->priv->preview), first, last);
529 /*--------------------------------------------------------------------------*/
530 /* PRIVATE. Simple last label spinbutton "changed" callback */
531 /*--------------------------------------------------------------------------*/
533 simple_last_spin_cb (GtkSpinButton *spinbutton,
538 first = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (op->priv->simple_first_spin));
539 last = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (op->priv->simple_last_spin));
541 /* Adjust range of first spin button. */
542 gtk_spin_button_set_range (GTK_SPIN_BUTTON (op->priv->simple_first_spin),
545 /* Update preview. */
546 gl_mini_preview_highlight_range (GL_MINI_PREVIEW (op->priv->preview), first, last);
551 /*--------------------------------------------------------------------------*/
552 /* PRIVATE. Preview "pressed" callback */
553 /*--------------------------------------------------------------------------*/
555 preview_pressed_cb (glMiniPreview *preview,
562 if ( !op->priv->merge_flag )
565 /* Update controls. */
566 old_first = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (op->priv->simple_first_spin));
567 if ( first > old_first )
569 gtk_spin_button_set_value (GTK_SPIN_BUTTON (op->priv->simple_last_spin), last);
570 gtk_spin_button_set_value (GTK_SPIN_BUTTON (op->priv->simple_first_spin), first);
574 gtk_spin_button_set_value (GTK_SPIN_BUTTON (op->priv->simple_first_spin), first);
575 gtk_spin_button_set_value (GTK_SPIN_BUTTON (op->priv->simple_last_spin), last);
577 if ( (first == 1) && (last == op->priv->labels_per_sheet) )
579 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (op->priv->simple_sheets_radio), TRUE);
580 gtk_spin_button_set_value (GTK_SPIN_BUTTON (op->priv->simple_sheets_spin), 1);
584 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (op->priv->simple_labels_radio), TRUE);
587 /* Update preview. */
588 gl_mini_preview_highlight_range (GL_MINI_PREVIEW (op->priv->preview), first, last);
594 /*--------------------------------------------------------------------------*/
595 /* PRIVATE. "changed" callback for merge first and copies spin buttons. */
596 /*--------------------------------------------------------------------------*/
598 merge_spin_cb (GtkSpinButton *spinbutton,
601 gint first, last, n_copies;
603 first = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (op->priv->merge_first_spin));
605 n_copies = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (op->priv->merge_copies_spin));
606 last = first + (n_copies * op->priv->n_records) - 1;
608 gl_mini_preview_highlight_range (GL_MINI_PREVIEW(op->priv->preview), first, last );
610 gtk_widget_set_sensitive (op->priv->merge_collate_check, (n_copies > 1));
611 gtk_widget_set_sensitive (op->priv->merge_collate_image, (n_copies > 1));
615 /*--------------------------------------------------------------------------*/
616 /* PRIVATE. Merge first collate check "toggled" callback */
617 /*--------------------------------------------------------------------------*/
619 merge_collate_check_cb (GtkToggleButton *togglebutton,
624 if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (op->priv->merge_collate_check)) )
626 pixbuf = gdk_pixbuf_new_from_xpm_data ( (const char **)collate_xpm);
630 pixbuf = gdk_pixbuf_new_from_xpm_data ( (const char **)nocollate_xpm);
633 gtk_image_set_from_pixbuf (GTK_IMAGE (op->priv->merge_collate_image), pixbuf);
637 /*--------------------------------------------------------------------------*/
638 /* PRIVATE. Preview "clicked" callback */
639 /*--------------------------------------------------------------------------*/
641 preview_clicked_cb (glMiniPreview *preview,
648 if ( op->priv->merge_flag )
651 /* Update controls. */
652 gtk_spin_button_set_value (GTK_SPIN_BUTTON (op->priv->merge_first_spin), first);
654 n_copies = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (op->priv->merge_copies_spin));
655 gtk_widget_set_sensitive (op->priv->merge_collate_check, (n_copies > 1));
656 gtk_widget_set_sensitive (op->priv->merge_collate_image, (n_copies > 1));
659 /* Update preview. */
660 last = first + (n_copies * op->priv->n_records) - 1;
661 gl_mini_preview_highlight_range (GL_MINI_PREVIEW (op->priv->preview), first, last);
670 * Local Variables: -- emacs
672 * c-basic-offset: 8 -- emacs
673 * tab-width: 8 -- emacs
674 * indent-tabs-mode: nil -- emacs