#include "output/cairo-pager.h"
#include "output/driver-provider.h"
#include "output/driver.h"
-#include "output/chart-item.h"
-#include "output/group-item.h"
-#include "output/message-item.h"
#include "output/output-item.h"
-#include "output/output-item-provider.h"
#include "output/pivot-table.h"
-#include "output/table-item.h"
-#include "output/text-item.h"
#include "gl/c-xvasprintf.h"
#include "gl/minmax.h"
{
struct output_item *item;
GtkWidget *drawing_area;
+ int width, height;
+ int nesting_depth;
};
struct psppire_output_view
glong y;
GtkTreeView *overview;
- GtkTreePath *cur_group;
GtkWidget *toplevel;
if (view->y > 0)
view->y += view->object_spacing;
- if (is_group_open_item (item->item))
+ if (item->item->type == OUTPUT_ITEM_GROUP)
continue;
r = xr_fsm_create_for_scrolling (item->item, view->style, cr);
gtk_layout_move (view->output, item->drawing_area, xpos, view->y);
}
- if (is_table_item (item->item))
- {
- const struct table_item *ti = to_table_item (item->item);
- gtk_widget_set_tooltip_text (item->drawing_area, ti->pt->notes);
- }
+ if (item->item->type == OUTPUT_ITEM_TABLE)
+ gtk_widget_set_tooltip_text (item->drawing_area,
+ item->item->table->notes);
{
gint minw;
cairo_region_destroy (region);
}
-
-void
-psppire_output_view_put (struct psppire_output_view *view,
- const struct output_item *item)
+static bool
+init_output_view_item (struct output_view_item *view_item,
+ struct psppire_output_view *view,
+ const struct output_item *item,
+ int nesting_depth)
{
- struct output_view_item *view_item;
- GtkWidget *drawing_area;
- int tw, th;
-
- if (is_group_close_item (item))
- {
- if (view->cur_group)
- {
- if (!gtk_tree_path_up (view->cur_group))
- {
- gtk_tree_path_free (view->cur_group);
- view->cur_group = NULL;
- }
- }
- return;
- }
- else if (is_text_item (item))
- {
- const struct text_item *text_item = to_text_item (item);
- const char *text = text_item_get_text (text_item);
- if (text[0] == '\0')
- return;
- }
-
- if (view->n_items >= view->allocated_items)
- view->items = x2nrealloc (view->items, &view->allocated_items,
- sizeof *view->items);
- view_item = &view->items[view->n_items++];
- view_item->item = output_item_ref (item);
- view_item->drawing_area = NULL;
+ *view_item = (struct output_view_item) {
+ .item = output_item_ref (item),
+ .nesting_depth = nesting_depth
+ };
GdkWindow *win = gtk_widget_get_window (GTK_WIDGET (view->output));
- if (is_group_open_item (item))
- tw = th = 0;
- else if (win)
+ if (win && item->type != OUTPUT_ITEM_GROUP)
{
- view_item->drawing_area = drawing_area = gtk_drawing_area_new ();
-
if (!view->style)
view->style = get_xr_fsm_style (view);
{
gdk_window_end_draw_frame (win, ctx);
cairo_region_destroy (region);
- return;
+
+ output_item_unref (view_item->item);
+ return false;
}
- xr_fsm_measure (r, cr, &tw, &th);
- create_drawing_area (view, drawing_area, r, tw, th, item);
+ xr_fsm_measure (r, cr, &view_item->width, &view_item->height);
+ view_item->drawing_area = gtk_drawing_area_new ();
+ create_drawing_area (view, view_item->drawing_area, r, view_item->width,
+ view_item->height, item);
gdk_window_end_draw_frame (win, ctx);
cairo_region_destroy (region);
}
- else
- tw = th = 0;
+ return true;
+}
+
+static void
+psppire_output_view_put__ (struct psppire_output_view *view,
+ const struct output_item *item,
+ GtkTreePath *parent_path)
+{
+ if (item->type == OUTPUT_ITEM_TEXT)
+ {
+ char *text = text_item_get_plain_text (item);
+ bool text_is_empty = text[0] == '\0';
+ free (text);
+ if (text_is_empty)
+ return;
+ }
+
+ if (view->n_items >= view->allocated_items)
+ view->items = x2nrealloc (view->items, &view->allocated_items,
+ sizeof *view->items);
+ struct output_view_item *view_item = &view->items[view->n_items];
+ if (!init_output_view_item (view_item, view, item,
+ parent_path ? gtk_tree_path_get_depth (parent_path) : 0))
+ return;
+ view->n_items++;
+
+ GtkTreePath *path = NULL;
if (view->overview)
{
GtkTreeStore *store = GTK_TREE_STORE (
/* Create a new node in the tree and puts a reference to it in 'iter'. */
GtkTreeIter iter;
GtkTreeIter parent;
- if (view->cur_group
- && gtk_tree_path_get_depth (view->cur_group) > 0
+ if (parent_path
+ && gtk_tree_path_get_depth (parent_path) > 0
&& gtk_tree_model_get_iter (GTK_TREE_MODEL (store),
- &parent, view->cur_group))
+ &parent, parent_path))
gtk_tree_store_append (store, &iter, &parent);
else
gtk_tree_store_append (store, &iter, NULL);
- if (is_group_open_item (item))
- {
- gtk_tree_path_free (view->cur_group);
- view->cur_group = gtk_tree_model_get_path (GTK_TREE_MODEL (store),
- &iter);
- }
-
gtk_tree_store_set (store, &iter,
COL_LABEL, output_item_get_label (item),
COL_ADDR, item,
COL_Y, view->y,
-1);
- GtkTreePath *path = gtk_tree_model_get_path (
+ /* Get the path of the new row. */
+ path = gtk_tree_model_get_path (
GTK_TREE_MODEL (store), &iter);
gtk_tree_view_expand_row (view->overview, path, TRUE);
- gtk_tree_path_free (path);
}
- if (view->max_width < tw)
- view->max_width = tw;
- view->y += th;
+ if (view->max_width < view_item->width)
+ view->max_width = view_item->width;
+ view->y += view_item->height;
gtk_layout_set_size (view->output, view->max_width, view->y);
+
+ if (item->type == OUTPUT_ITEM_GROUP)
+ for (size_t i = 0; i < item->group.n_children; i++)
+ psppire_output_view_put__ (view, item->group.children[i], path);
+
+ gtk_tree_path_free (path);
+}
+
+void
+psppire_output_view_put (struct psppire_output_view *view,
+ const struct output_item *item)
+{
+ psppire_output_view_put__ (view, item, NULL);
}
static void
{
GtkTargetList *tl = gtk_target_list_new (targets, G_N_ELEMENTS (targets));
g_return_val_if_fail (tl, NULL);
- if (is_table_item (item) ||
- is_chart_item (item))
+ if (item->type == OUTPUT_ITEM_TABLE || item->type == OUTPUT_ITEM_CHART)
gtk_target_list_add_image_targets (tl, SELECT_FMT_IMG, TRUE);
return tl;
}
psppire_output_view_new (GtkLayout *output, GtkTreeView *overview)
{
struct psppire_output_view *view;
- GtkTreeViewColumn *column;
- GtkCellRenderer *renderer;
-
- GtkTreeModel *model;
view = xmalloc (sizeof *view);
*view = (struct psppire_output_view) {
{
g_signal_connect (overview, "realize", G_CALLBACK (on_realize), view);
- model = GTK_TREE_MODEL (gtk_tree_store_new (
+ GtkTreeModel *model = GTK_TREE_MODEL (gtk_tree_store_new (
N_COLS,
G_TYPE_STRING, /* COL_LABEL */
G_TYPE_POINTER, /* COL_ADDR */
gtk_tree_view_set_model (overview, model);
g_object_unref (model);
- column = gtk_tree_view_column_new ();
+ GtkTreeViewColumn *column = gtk_tree_view_column_new ();
gtk_tree_view_append_column (GTK_TREE_VIEW (overview), column);
- renderer = gtk_cell_renderer_text_new ();
+ GtkCellRenderer * 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_LABEL);
if (view->print_settings != NULL)
g_object_unref (view->print_settings);
- if (view->cur_group)
- gtk_tree_path_free (view->cur_group);
-
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;
-}
-
/* Export. */
void
size_t i;
for (i = 0; i < view->n_items; i++)
- driver->class->submit (driver, view->items[i].item);
+ if (view->items[i].nesting_depth == 0)
+ driver->class->submit (driver, view->items[i].item);
output_driver_destroy (driver);
}
}
complete. Don't let that screw up printing. */
return TRUE;
}
- else if (view->print_item < view->n_items)
+
+ while (view->print_item < view->n_items)
{
- xr_pager_add_item (view->pager, view->items[view->print_item++].item);
- while (xr_pager_needs_new_page (view->pager))
- {
- xr_pager_add_page (view->pager,
- get_cairo_context_from_print_context (context));
- view->print_n_pages ++;
- }
- return FALSE;
+ const struct output_view_item *item = &view->items[view->print_item++];
+ if (item->nesting_depth == 0)
+ {
+ xr_pager_add_item (view->pager, item->item);
+ while (xr_pager_needs_new_page (view->pager))
+ {
+ xr_pager_add_page (view->pager,
+ get_cairo_context_from_print_context (context));
+ view->print_n_pages ++;
+ }
+ return FALSE;
+ }
}
- else
- {
- gtk_print_operation_set_n_pages (operation, MAX (1, view->print_n_pages));
- /* Re-create the driver to do the real printing. */
- xr_pager_destroy (view->pager);
- view->pager = xr_pager_create (view->page_style, view->fsm_style);
- view->print_item = 0;
- view->paginated = TRUE;
+ gtk_print_operation_set_n_pages (operation, MAX (1, view->print_n_pages));
- return TRUE;
- }
+ /* Re-create the driver to do the real printing. */
+ xr_pager_destroy (view->pager);
+ view->pager = xr_pager_create (view->page_style, view->fsm_style);
+ view->print_item = 0;
+ view->paginated = TRUE;
+
+ return TRUE;
}
static void
get_cairo_context_from_print_context (context));
while (!xr_pager_needs_new_page (view->pager)
&& view->print_item < view->n_items)
- xr_pager_add_item (view->pager, view->items [view->print_item++].item);
+ {
+ const struct output_view_item *item = &view->items [view->print_item++];
+ if (item->nesting_depth == 0)
+ xr_pager_add_item (view->pager, item->item);
+ }
}
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);
-}