psppire-output-view: Properly render the first few items of output.
[pspp] / src / ui / gui / psppire-output-view.c
index f1397aa792f5d9b855b2c87ad6e76c4a635b6f51..6e9858c576180c8c2a3d6b93e593dc95a4d38d09 100644 (file)
@@ -76,9 +76,9 @@ struct psppire_output_view
 
 enum
   {
-    COL_TITLE,                  /* Table title. */
+    COL_NAME,                   /* Table name. */
     COL_ADDR,                   /* Pointer to the table */
-    COL_Y,                      /* Y position of top of title. */
+    COL_Y,                      /* Y position of top of name. */
     N_COLS
   };
 
@@ -188,13 +188,32 @@ create_xr (struct psppire_output_view *view)
   cairo_destroy (cr);
 }
 
+static void
+create_drawing_area (struct psppire_output_view *view,
+                     GtkWidget *drawing_area, struct xr_rendering *r,
+                     int tw, int th)
+{
+  g_object_set_data_full (G_OBJECT (drawing_area),
+                          "rendering", r, free_rendering);
+
+  g_signal_connect (drawing_area, "realize",
+                    G_CALLBACK (on_dwgarea_realize), view);
+  g_signal_connect (drawing_area, "expose_event",
+                    G_CALLBACK (expose_event_callback), view);
+
+  gtk_widget_set_size_request (drawing_area, tw, th);
+  gtk_layout_put (view->output, drawing_area, 0, view->y);
+
+  gtk_widget_show (drawing_area);
+}
+
 static void
 rerender (struct psppire_output_view *view)
 {
   struct output_view_item *item;
   cairo_t *cr;
 
-  if (!view->n_items)
+  if (!view->n_items || !GTK_WIDGET (view->output)->window)
     return;
 
   string_map_clear (&view->render_opts);
@@ -221,10 +240,19 @@ rerender (struct psppire_output_view *view)
         }
 
       xr_rendering_measure (r, &tw, &th);
-      g_object_set_data_full (G_OBJECT (item->drawing_area),
-                              "rendering", r, free_rendering);
-      gtk_widget_set_size_request (item->drawing_area, tw, th);
-      gtk_layout_move (view->output, item->drawing_area, 0, view->y);
+
+      if (!item->drawing_area)
+        {
+          item->drawing_area = gtk_drawing_area_new ();
+          create_drawing_area (view, item->drawing_area, r, tw, th);
+        }
+      else
+        {
+          g_object_set_data_full (G_OBJECT (item->drawing_area),
+                                  "rendering", r, free_rendering);
+          gtk_widget_set_size_request (item->drawing_area, tw, th);
+          gtk_layout_move (view->output, item->drawing_area, 0, view->y);
+        }
 
       if (view->max_width < tw)
         view->max_width = tw;
@@ -239,13 +267,14 @@ void
 psppire_output_view_put (struct psppire_output_view *view,
                          const struct output_item *item)
 {
+  struct output_view_item *view_item;
   GtkWidget *drawing_area;
   struct xr_rendering *r;
-  struct string title;
+  struct string name;
   GtkTreeStore *store;
+  cairo_t *cr = NULL;
   GtkTreePath *path;
   GtkTreeIter iter;
-  cairo_t *cr;
   int tw, th;
 
   if (is_text_item (item))
@@ -266,33 +295,31 @@ psppire_output_view_put (struct psppire_output_view *view,
   if (view->n_items >= view->allocated_items)
     view->items = x2nrealloc (view->items, &view->allocated_items,
                                 sizeof *view->items);
-  view->items[view->n_items].item = output_item_ref (item);
-  view->items[view->n_items].drawing_area = drawing_area = gtk_drawing_area_new ();
-  view->n_items++;
-
-  cr = gdk_cairo_create (GTK_WIDGET (view->output)->window);
-  if (view->xr == NULL)
-    create_xr (view);
+  view_item = &view->items[view->n_items++];
+  view_item->item = output_item_ref (item);
+  view_item->drawing_area = NULL;
 
-  if (view->y > 0)
-    view->y += view->font_height / 2;
+  if (GTK_WIDGET (view->output)->window)
+    {
+      view_item->drawing_area = drawing_area = gtk_drawing_area_new ();
 
-  r = xr_rendering_create (view->xr, item, cr);
-  if (r == NULL)
-    goto done;
+      cr = gdk_cairo_create (GTK_WIDGET (view->output)->window);
+      if (view->xr == NULL)
+        create_xr (view);
 
-  xr_rendering_measure (r, &tw, &th);
+      if (view->y > 0)
+        view->y += view->font_height / 2;
 
-  g_object_set_data_full (G_OBJECT (drawing_area), "rendering", r, free_rendering);
-  g_signal_connect (drawing_area, "realize",
-                    G_CALLBACK (on_dwgarea_realize), view);
-  g_signal_connect (drawing_area, "expose_event",
-                    G_CALLBACK (expose_event_callback), view);
+      r = xr_rendering_create (view->xr, item, cr);
+      if (r == NULL)
+        goto done;
 
-  gtk_widget_set_size_request (drawing_area, tw, th);
-  gtk_layout_put (view->output, drawing_area, 0, view->y);
+      xr_rendering_measure (r, &tw, &th);
 
-  gtk_widget_show (drawing_area);
+      create_drawing_area (view, drawing_area, r, tw, th);
+    }
+  else
+    tw = th = 0;
 
   if (view->overview
       && (!is_text_item (item)
@@ -301,7 +328,7 @@ psppire_output_view_put (struct psppire_output_view *view,
     {
       store = GTK_TREE_STORE (gtk_tree_view_get_model (view->overview));
 
-      ds_init_empty (&title);
+      ds_init_empty (&name);
       if (is_text_item (item)
           && text_item_get_type (to_text_item (item)) == TEXT_ITEM_COMMAND_OPEN)
         {
@@ -315,38 +342,38 @@ psppire_output_view_put (struct psppire_output_view *view,
           gtk_tree_store_append (store, &iter, p);
         }
 
-      ds_clear (&title);
+      ds_clear (&name);
       if (is_text_item (item))
-        ds_put_cstr (&title, text_item_get_text (to_text_item (item)));
+        ds_put_cstr (&name, text_item_get_text (to_text_item (item)));
       else if (is_message_item (item))
         {
           const struct message_item *msg_item = to_message_item (item);
           const struct msg *msg = message_item_get_msg (msg_item);
-          ds_put_format (&title, "%s: %s", _("Message"),
+          ds_put_format (&name, "%s: %s", _("Message"),
                          msg_severity_to_string (msg->severity));
         }
       else if (is_table_item (item))
         {
-          const char *caption = table_item_get_caption (to_table_item (item));
-          if (caption != NULL)
-            ds_put_format (&title, "Table: %s", caption);
+          const char *title = table_item_get_title (to_table_item (item));
+          if (title != NULL)
+            ds_put_format (&name, "Table: %s", title);
           else
-            ds_put_cstr (&title, "Table");
+            ds_put_cstr (&name, "Table");
         }
       else if (is_chart_item (item))
         {
           const char *s = chart_item_get_title (to_chart_item (item));
           if (s != NULL)
-            ds_put_format (&title, "Chart: %s", s);
+            ds_put_format (&name, "Chart: %s", s);
           else
-            ds_put_cstr (&title, "Chart");
+            ds_put_cstr (&name, "Chart");
         }
       gtk_tree_store_set (store, &iter,
-                          COL_TITLE, ds_cstr (&title),
+                          COL_NAME, ds_cstr (&name),
                          COL_ADDR, item,
                           COL_Y, view->y,
                           -1);
-      ds_destroy (&title);
+      ds_destroy (&name);
 
       path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
       gtk_tree_view_expand_row (view->overview, path, TRUE);
@@ -643,7 +670,7 @@ psppire_output_view_new (GtkLayout *output, GtkTreeView *overview,
     {
       model = GTK_TREE_MODEL (gtk_tree_store_new (
                                 N_COLS,
-                                G_TYPE_STRING,  /* COL_TITLE */
+                                G_TYPE_STRING,  /* COL_NAME */
                                 G_TYPE_POINTER, /* COL_ADDR */
                                 G_TYPE_LONG));  /* COL_Y */
       gtk_tree_view_set_model (overview, model);
@@ -658,7 +685,7 @@ psppire_output_view_new (GtkLayout *output, GtkTreeView *overview,
       gtk_tree_view_append_column (GTK_TREE_VIEW (overview), column);
       renderer = gtk_cell_renderer_text_new ();
       gtk_tree_view_column_pack_start (column, renderer, TRUE);
-      gtk_tree_view_column_add_attribute (column, renderer, "text", COL_TITLE);
+      gtk_tree_view_column_add_attribute (column, renderer, "text", COL_NAME);
 
       g_signal_connect (GTK_TREE_VIEW (overview),
                         "row-activated", G_CALLBACK (on_row_activate), view);
@@ -699,6 +726,25 @@ psppire_output_view_destroy (struct psppire_output_view *view)
 
   free (view);
 }
+
+void
+psppire_output_view_clear (struct psppire_output_view *view)
+{
+  size_t i;
+
+  view->max_width = 0;
+  view->y = 0;
+
+  for (i = 0; i < view->n_items; i++)
+    {
+      gtk_container_remove (GTK_CONTAINER (view->output),
+                            view->items[i].drawing_area);
+      output_item_unref (view->items[i].item);
+    }
+  free (view->items);
+  view->items = NULL;
+  view->n_items = view->allocated_items = 0;
+}
 \f
 /* Export. */
 
@@ -874,3 +920,47 @@ psppire_output_view_print (struct psppire_output_view *view,
 
   g_object_unref (print);
 }
+\f
+struct psppire_output_view_driver
+  {
+    struct output_driver driver;
+    struct psppire_output_view *view;
+  };
+
+static struct psppire_output_view_driver *
+psppire_output_view_driver_cast (struct output_driver *driver)
+{
+  return UP_CAST (driver, struct psppire_output_view_driver, driver);
+}
+
+static void
+psppire_output_view_submit (struct output_driver *this,
+                            const struct output_item *item)
+{
+  struct psppire_output_view_driver *povd = psppire_output_view_driver_cast (this);
+
+  if (is_table_item (item))
+    psppire_output_view_put (povd->view, item);
+}
+
+static struct output_driver_class psppire_output_view_driver_class =
+  {
+    "PSPPIRE Output View",      /* name */
+    NULL,                       /* destroy */
+    psppire_output_view_submit, /* submit */
+    NULL,                       /* flush */
+  };
+
+void
+psppire_output_view_register_driver (struct psppire_output_view *view)
+{
+  struct psppire_output_view_driver *povd;
+  struct output_driver *d;
+
+  povd = xzalloc (sizeof *povd);
+  povd->view = view;
+  d = &povd->driver;
+  output_driver_init (d, &psppire_output_view_driver_class, "PSPPIRE Output View",
+                      SETTINGS_DEVICE_UNFILTERED);
+  output_driver_register (d);
+}