+#include <math.h>
#include <pango/pangocairo.h>
#include <gtk/gtk.h>
-#include <gtk/gtkprintoperation.h>
static GtkWidget *main_window;
static char *filename = NULL;
gtk_print_operation_set_n_pages (operation, g_list_length (page_breaks) + 1);
print_data->page_breaks = page_breaks;
-
}
static void
int start, end, i;
PangoLayoutIter *iter;
double start_pos;
+
if (page_nr == 0)
start = 0;
else
}
while (i < end &&
pango_layout_iter_next_line (iter));
+
+ pango_layout_iter_free (iter);
}
static void
{
GtkPageSetup *new_page_setup;
- if (settings == NULL)
- settings = gtk_print_settings_new ();
-
new_page_setup = gtk_print_run_page_setup_dialog (GTK_WINDOW (main_window),
page_setup, settings);
GtkWidget *vbox, *hbox, *font, *label;
gtk_print_operation_set_custom_tab_label (operation, "Other");
- vbox = gtk_vbox_new (FALSE, 0);
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
- hbox = gtk_hbox_new (FALSE, 8);
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
data->font = g_strdup (selected_font);
}
+typedef struct
+{
+ GtkPrintOperation *op;
+ GtkPrintOperationPreview *preview;
+ GtkPrintContext *context;
+ GtkWidget *spin;
+ GtkWidget *area;
+ gint page;
+ PrintData *data;
+ gdouble dpi_x, dpi_y;
+} PreviewOp;
+
+static gboolean
+preview_draw (GtkWidget *widget,
+ cairo_t *cr,
+ gpointer data)
+{
+ PreviewOp *pop = data;
+ cairo_t *prev_cr;
+ double dpi_x, dpi_y;
+
+ prev_cr = gtk_print_context_get_cairo_context (pop->context);
+ cairo_reference (prev_cr);
+ dpi_x = gtk_print_context_get_dpi_x (pop->context);
+ dpi_y = gtk_print_context_get_dpi_y (pop->context);
+
+ gtk_print_context_set_cairo_context (pop->context,
+ cr, dpi_x, dpi_y);
+ gtk_print_operation_preview_render_page (pop->preview,
+ pop->page - 1);
+ gtk_print_context_set_cairo_context (pop->context,
+ prev_cr, dpi_x, dpi_y);
+ cairo_destroy (prev_cr);
+
+ return TRUE;
+}
+
static void
-do_print (GtkAction *action)
+preview_ready (GtkPrintOperationPreview *preview,
+ GtkPrintContext *context,
+ gpointer data)
{
- GtkWidget *error_dialog;
- GtkPrintOperation *print;
- PrintData print_data;
- GtkPrintOperationResult res;
- GError *error;
+ PreviewOp *pop = data;
+ gint n_pages;
- print_data.text = get_text ();
- print_data.font = g_strdup ("Sans 12");
+ g_object_get (pop->op, "n-pages", &n_pages, NULL);
- print = gtk_print_operation_new ();
+ gtk_spin_button_set_range (GTK_SPIN_BUTTON (pop->spin),
+ 1.0, n_pages);
- gtk_print_operation_set_track_print_status (print, TRUE);
-
- if (settings != NULL)
- gtk_print_operation_set_print_settings (print, settings);
+ g_signal_connect (pop->area, "draw",
+ G_CALLBACK (preview_draw),
+ pop);
- if (page_setup != NULL)
- gtk_print_operation_set_default_page_setup (print, page_setup);
-
- g_signal_connect (print, "begin_print", G_CALLBACK (begin_print), &print_data);
- g_signal_connect (print, "draw_page", G_CALLBACK (draw_page), &print_data);
- g_signal_connect (print, "create_custom_widget", G_CALLBACK (create_custom_widget), &print_data);
- g_signal_connect (print, "custom_widget_apply", G_CALLBACK (custom_widget_apply), &print_data);
-
- error = NULL;
- res = gtk_print_operation_run (print, GTK_WINDOW (main_window), &error);
+ gtk_widget_queue_draw (pop->area);
+}
+
+static void
+preview_got_page_size (GtkPrintOperationPreview *preview,
+ GtkPrintContext *context,
+ GtkPageSetup *page_setup,
+ gpointer data)
+{
+ PreviewOp *pop = data;
+ GtkAllocation allocation;
+ GtkPaperSize *paper_size;
+ double w, h;
+ cairo_t *cr;
+ gdouble dpi_x, dpi_y;
+
+ paper_size = gtk_page_setup_get_paper_size (page_setup);
+
+ w = gtk_paper_size_get_width (paper_size, GTK_UNIT_INCH);
+ h = gtk_paper_size_get_height (paper_size, GTK_UNIT_INCH);
+
+ cr = gdk_cairo_create (gtk_widget_get_window (pop->area));
+
+ gtk_widget_get_allocation (pop->area, &allocation);
+ dpi_x = allocation.width/w;
+ dpi_y = allocation.height/h;
+
+ if (fabs (dpi_x - pop->dpi_x) > 0.001 ||
+ fabs (dpi_y - pop->dpi_y) > 0.001)
+ {
+ gtk_print_context_set_cairo_context (context, cr, dpi_x, dpi_y);
+ pop->dpi_x = dpi_x;
+ pop->dpi_y = dpi_y;
+ }
+
+ pango_cairo_update_layout (cr, pop->data->layout);
+ cairo_destroy (cr);
+}
+
+static void
+update_page (GtkSpinButton *widget,
+ gpointer data)
+{
+ PreviewOp *pop = data;
+
+ pop->page = gtk_spin_button_get_value_as_int (widget);
+ gtk_widget_queue_draw (pop->area);
+}
+
+static void
+preview_destroy (GtkWindow *window,
+ PreviewOp *pop)
+{
+ gtk_print_operation_preview_end_preview (pop->preview);
+ g_object_unref (pop->op);
+
+ g_free (pop);
+}
+
+static gboolean
+preview_cb (GtkPrintOperation *op,
+ GtkPrintOperationPreview *preview,
+ GtkPrintContext *context,
+ GtkWindow *parent,
+ gpointer data)
+{
+ GtkWidget *window, *close, *page, *hbox, *vbox, *da;
+ gdouble width, height;
+ cairo_t *cr;
+ PreviewOp *pop;
+ PrintData *print_data = data;
+
+ pop = g_new0 (PreviewOp, 1);
+
+ pop->data = print_data;
+
+ width = 200;
+ height = 300;
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_transient_for (GTK_WINDOW (window),
+ GTK_WINDOW (main_window));
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox,
+ FALSE, FALSE, 0);
+ page = gtk_spin_button_new_with_range (1, 100, 1);
+ gtk_box_pack_start (GTK_BOX (hbox), page, FALSE, FALSE, 0);
+
+ close = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
+ gtk_box_pack_start (GTK_BOX (hbox), close, FALSE, FALSE, 0);
+
+ da = gtk_drawing_area_new ();
+ gtk_widget_set_size_request (GTK_WIDGET (da), width, height);
+ gtk_box_pack_start (GTK_BOX (vbox), da, TRUE, TRUE, 0);
+
+ gtk_widget_realize (da);
+
+ cr = gdk_cairo_create (gtk_widget_get_window (da));
+ /* TODO: What dpi to use here? This will be used for pagination.. */
+ gtk_print_context_set_cairo_context (context, cr, 72, 72);
+ cairo_destroy (cr);
+
+ pop->op = g_object_ref (op);
+ pop->preview = preview;
+ pop->context = context;
+ pop->spin = page;
+ pop->area = da;
+ pop->page = 1;
+
+ g_signal_connect (page, "value-changed",
+ G_CALLBACK (update_page), pop);
+ g_signal_connect_swapped (close, "clicked",
+ G_CALLBACK (gtk_widget_destroy), window);
+
+ g_signal_connect (preview, "ready",
+ G_CALLBACK (preview_ready), pop);
+ g_signal_connect (preview, "got-page-size",
+ G_CALLBACK (preview_got_page_size), pop);
+
+ g_signal_connect (window, "destroy",
+ G_CALLBACK (preview_destroy), pop);
+
+ gtk_widget_show_all (window);
+
+ return TRUE;
+}
+
+static void
+print_done (GtkPrintOperation *op,
+ GtkPrintOperationResult res,
+ PrintData *print_data)
+{
+ GError *error = NULL;
if (res == GTK_PRINT_OPERATION_RESULT_ERROR)
{
+
+ GtkWidget *error_dialog;
+
+ gtk_print_operation_get_error (op, &error);
+
error_dialog = gtk_message_dialog_new (GTK_WINDOW (main_window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"Error printing file:\n%s",
- error->message);
+ error ? error->message : "no details");
g_signal_connect (error_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (error_dialog);
- g_error_free (error);
}
else if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
{
if (settings != NULL)
g_object_unref (settings);
- settings = g_object_ref (gtk_print_operation_get_print_settings (print));
+ settings = g_object_ref (gtk_print_operation_get_print_settings (op));
}
- if (!gtk_print_operation_is_finished (print))
+ g_free (print_data->text);
+ g_free (print_data->font);
+ g_free (print_data);
+
+ if (!gtk_print_operation_is_finished (op))
{
- g_object_ref (print);
- active_prints = g_list_append (active_prints, print);
+ g_object_ref (op);
+ active_prints = g_list_append (active_prints, op);
update_statusbar ();
/* This ref is unref:ed when we get the final state change */
- g_signal_connect (print, "status_changed",
+ g_signal_connect (op, "status_changed",
G_CALLBACK (status_changed_cb), NULL);
}
+}
+
+static void
+end_print (GtkPrintOperation *op, GtkPrintContext *context, PrintData *print_data)
+{
+ g_list_free (print_data->page_breaks);
+ print_data->page_breaks = NULL;
+ g_object_unref (print_data->layout);
+ print_data->layout = NULL;
+}
+
+static void
+do_print_or_preview (GtkAction *action, GtkPrintOperationAction print_action)
+{
+ GtkPrintOperation *print;
+ PrintData *print_data;
+
+ print_data = g_new0 (PrintData, 1);
+
+ print_data->text = get_text ();
+ print_data->font = g_strdup ("Sans 12");
+
+ print = gtk_print_operation_new ();
+
+ gtk_print_operation_set_track_print_status (print, TRUE);
+
+ if (settings != NULL)
+ gtk_print_operation_set_print_settings (print, settings);
+
+ if (page_setup != NULL)
+ gtk_print_operation_set_default_page_setup (print, page_setup);
+
+ g_signal_connect (print, "begin_print", G_CALLBACK (begin_print), print_data);
+ g_signal_connect (print, "end-print", G_CALLBACK (end_print), print_data);
+ g_signal_connect (print, "draw_page", G_CALLBACK (draw_page), print_data);
+ g_signal_connect (print, "create_custom_widget", G_CALLBACK (create_custom_widget), print_data);
+ g_signal_connect (print, "custom_widget_apply", G_CALLBACK (custom_widget_apply), print_data);
+ g_signal_connect (print, "preview", G_CALLBACK (preview_cb), print_data);
+
+ g_signal_connect (print, "done", G_CALLBACK (print_done), print_data);
+
+ gtk_print_operation_set_export_filename (print, "test.pdf");
+
+#if 0
+ gtk_print_operation_set_allow_async (print, TRUE);
+#endif
+ gtk_print_operation_run (print, print_action, GTK_WINDOW (main_window), NULL);
g_object_unref (print);
- g_free (print_data.text);
- g_free (print_data.font);
+}
+
+static void
+do_print (GtkAction *action)
+{
+ do_print_or_preview (action, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG);
+}
+
+static void
+do_preview (GtkAction *action)
+{
+ do_print_or_preview (action, GTK_PRINT_OPERATION_ACTION_PREVIEW);
}
static void
"Page _Setup", NULL, /* label, accelerator */
"Set up the page", /* tooltip */
G_CALLBACK (do_page_setup) },
+ { "Preview", NULL, /* name, stock id */
+ "Print Preview", NULL, /* label, accelerator */
+ "Preview the printed document", /* tooltip */
+ G_CALLBACK (do_preview) },
{ "Print", GTK_STOCK_PRINT, /* name, stock id */
NULL, NULL, /* label, accelerator */
"Print the document", /* tooltip */
- G_CALLBACK (do_print) },
+ G_CALLBACK (do_print) }
};
static guint n_entries = G_N_ELEMENTS (entries);
" <menuitem action='Save'/>"
" <menuitem action='SaveAs'/>"
" <menuitem action='PageSetup'/>"
+" <menuitem action='Preview'/>"
" <menuitem action='Print'/>"
" <separator/>"
" <menuitem action='Quit'/>"
update_statusbar ();
}
-static void
-update_resize_grip (GtkWidget *widget,
- GdkEventWindowState *event,
- GtkStatusbar *statusbar)
-{
- if (event->changed_mask & (GDK_WINDOW_STATE_MAXIMIZED |
- GDK_WINDOW_STATE_FULLSCREEN))
- {
- gboolean maximized;
-
- maximized = event->new_window_state & (GDK_WINDOW_STATE_MAXIMIZED |
- GDK_WINDOW_STATE_FULLSCREEN);
- gtk_statusbar_set_has_resize_grip (statusbar, !maximized);
- }
-}
-
static void
create_window (void)
{
GtkWidget *bar;
- GtkWidget *table;
+ GtkWidget *box;
GtkWidget *contents;
GtkUIManager *ui;
GtkWidget *sw;
GtkActionGroup *actions;
GError *error;
+ GtkWindowGroup *group;
main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ group = gtk_window_group_new ();
+ gtk_window_group_add_window (group, GTK_WINDOW (main_window));
+ g_object_unref (group);
+
gtk_window_set_default_size (GTK_WINDOW (main_window),
400, 600);
g_error_free (error);
}
- table = gtk_table_new (1, 3, FALSE);
- gtk_container_add (GTK_CONTAINER (main_window), table);
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_container_add (GTK_CONTAINER (main_window), box);
bar = gtk_ui_manager_get_widget (ui, "/MenuBar");
gtk_widget_show (bar);
- gtk_table_attach (GTK_TABLE (table),
- bar,
- /* X direction */ /* Y direction */
- 0, 1, 0, 1,
- GTK_EXPAND | GTK_FILL, 0,
- 0, 0);
+ gtk_container_add (GTK_CONTAINER (box), bar);
/* Create document */
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
GTK_SHADOW_IN);
- gtk_table_attach (GTK_TABLE (table),
- sw,
- /* X direction */ /* Y direction */
- 0, 1, 1, 2,
- GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
- 0, 0);
+ gtk_widget_set_vexpand (sw, TRUE);
+ gtk_container_add (GTK_CONTAINER (box), sw);
contents = gtk_text_view_new ();
gtk_widget_grab_focus (contents);
/* Create statusbar */
statusbar = gtk_statusbar_new ();
- gtk_table_attach (GTK_TABLE (table),
- statusbar,
- /* X direction */ /* Y direction */
- 0, 1, 2, 3,
- GTK_EXPAND | GTK_FILL, 0,
- 0, 0);
+ gtk_container_add (GTK_CONTAINER (box), statusbar);
/* Show text widget info in the statusbar */
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (contents));
G_CALLBACK (mark_set_callback),
NULL,
0);
-
- g_signal_connect_object (main_window,
- "window_state_event",
- G_CALLBACK (update_resize_grip),
- statusbar,
- 0);
-
+
update_ui ();
gtk_widget_show_all (main_window);
int
main (int argc, char **argv)
{
+ GError *error = NULL;
+
g_set_application_name ("Print editor");
gtk_init (&argc, &argv);
+ settings = gtk_print_settings_new_from_file ("print-settings.ini", &error);
+ if (error) {
+ g_print ("Failed to load print settings: %s\n", error->message);
+ g_clear_error (&error);
+
+ settings = gtk_print_settings_new ();
+ }
+ g_assert (settings != NULL);
+
+ page_setup = gtk_page_setup_new_from_file ("page-setup.ini", &error);
+ if (error) {
+ g_print ("Failed to load page setup: %s\n", error->message);
+ g_clear_error (&error);
+ }
+
create_window ();
if (argc == 2)
load_file (argv[1]);
gtk_main ();
+
+ if (!gtk_print_settings_to_file (settings, "print-settings.ini", &error)) {
+ g_print ("Failed to save print settings: %s\n", error->message);
+ g_clear_error (&error);
+ }
+ if (page_setup &&
+ !gtk_page_setup_to_file (page_setup, "page-setup.ini", &error)) {
+ g_print ("Failed to save page setup: %s\n", error->message);
+ g_clear_error (&error);
+ }
+
return 0;
}