]> Pileus Git - ~andy/gtk/blobdiff - tests/print-editor.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / tests / print-editor.c
index c49ede459bb7cd1a038f0143290c3f33c689ec46..e8399ceb6dc2d028c039d00212a2b2439d896d41 100644 (file)
@@ -1,6 +1,6 @@
+#include <math.h>
 #include <pango/pangocairo.h>
 #include <gtk/gtk.h>
-#include <gtk/gtkprintoperation.h>
 
 static GtkWidget *main_window;
 static char *filename = NULL;
@@ -303,7 +303,6 @@ begin_print (GtkPrintOperation *operation,
   gtk_print_operation_set_n_pages (operation, g_list_length (page_breaks) + 1);
   
   print_data->page_breaks = page_breaks;
-  
 }
 
 static void
@@ -317,6 +316,7 @@ draw_page (GtkPrintOperation *operation,
   int start, end, i;
   PangoLayoutIter *iter;
   double start_pos;
+
   if (page_nr == 0)
     start = 0;
   else
@@ -362,6 +362,8 @@ draw_page (GtkPrintOperation *operation,
     }
   while (i < end &&
         pango_layout_iter_next_line (iter));
+
+  pango_layout_iter_free (iter);
 }
 
 static void
@@ -369,9 +371,6 @@ do_page_setup (GtkAction *action)
 {
   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);
 
@@ -400,10 +399,10 @@ create_custom_widget (GtkPrintOperation *operation,
   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);
 
@@ -430,69 +429,293 @@ custom_widget_apply (GtkPrintOperation *operation,
   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
@@ -548,10 +771,14 @@ static GtkActionEntry entries[] = {
     "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);
 
@@ -564,6 +791,7 @@ static const gchar *ui_info =
 "      <menuitem action='Save'/>"
 "      <menuitem action='SaveAs'/>"
 "      <menuitem action='PageSetup'/>"
+"      <menuitem action='Preview'/>"
 "      <menuitem action='Print'/>"
 "      <separator/>"
 "      <menuitem action='Quit'/>"
@@ -590,35 +818,24 @@ mark_set_callback (GtkTextBuffer     *buffer,
   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);
   
@@ -641,17 +858,12 @@ create_window (void)
       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);
@@ -663,12 +875,8 @@ create_window (void)
   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);
@@ -679,12 +887,7 @@ create_window (void)
   /* 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));
@@ -700,13 +903,7 @@ create_window (void)
                           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);
@@ -715,14 +912,42 @@ create_window (void)
 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;
 }