X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Fpsppire-output-view.c;h=2ac85a52ada2e3418963a86fbab8cb6718fd5865;hb=db83cfb8d09e5ef9aecd905e7fd6ac7973088bed;hp=4205befaeb12c30c2e1016e36cf0fd77c3ed7235;hpb=d18e5ef8b730eda2c87a596cf51159dd5044e541;p=pspp diff --git a/src/ui/gui/psppire-output-view.c b/src/ui/gui/psppire-output-view.c index 4205befaeb..2ac85a52ad 100644 --- a/src/ui/gui/psppire-output-view.c +++ b/src/ui/gui/psppire-output-view.c @@ -30,6 +30,7 @@ #include "output/group-item.h" #include "output/message-item.h" #include "output/output-item.h" +#include "output/output-item-provider.h" #include "output/table-item.h" #include "output/text-item.h" @@ -59,8 +60,7 @@ struct psppire_output_view struct string_map render_opts; GtkTreeView *overview; - GtkTreeIter cur_command; - bool in_command; + GtkTreePath *cur_group; GtkWidget *toplevel; @@ -122,43 +122,25 @@ free_rendering (gpointer rendering_) } static void -create_xr (struct psppire_output_view *view) +get_xr_options (struct psppire_output_view *view, struct string_map *options) { - struct text_item *text_item; - PangoFontDescription *font_desc; - struct xr_rendering *r; - char *font_name; - int font_width; - cairo_t *cr; - gchar *fgc; + string_map_clear (options); - GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET (view->output)); + GtkStyleContext *context + = gtk_widget_get_style_context (GTK_WIDGET (view->output)); GtkStateFlags state = gtk_widget_get_state_flags (GTK_WIDGET (view->output)); - GdkRGBA *fg_color; - - gtk_style_context_get (context, state, - "font", &font_desc, "color", &fg_color, NULL); - - cr = gdk_cairo_create (gtk_widget_get_window (GTK_WIDGET (view->output))); - - /* Set the widget's text color as the foreground color for the output driver */ - /* gdk_rgba_to_string() would be perfect, but xr's parse_color does not */ - /* understand the rgb(255,128,33) format. Therefore we do it ourself. */ - fgc = xasprintf("#%4x%4x%4x",(int)(fg_color->red*0xffff), - (int)(fg_color->green*0xffff),(int)(fg_color->blue*0xffff)); - string_map_insert (&view->render_opts, "foreground-color", fgc); - g_free (fgc); - gdk_rgba_free (fg_color); /* Use GTK+ default font as proportional font. */ - font_name = pango_font_description_to_string (font_desc); - string_map_insert (&view->render_opts, "prop-font", font_name); + PangoFontDescription *font_desc; + gtk_style_context_get (context, state, "font", &font_desc, NULL); + char *font_name = pango_font_description_to_string (font_desc); + string_map_insert (options, "prop-font", font_name); g_free (font_name); /* Derived emphasized font from proportional font. */ pango_font_description_set_style (font_desc, PANGO_STYLE_ITALIC); font_name = pango_font_description_to_string (font_desc); - string_map_insert (&view->render_opts, "emph-font", font_name); + string_map_insert (options, "emph-font", font_name); g_free (font_name); pango_font_description_free (font_desc); @@ -167,21 +149,39 @@ create_xr (struct psppire_output_view *view) scrolling only. (The length should not be increased very much because it is already close enough to INT_MAX when expressed as thousands of a point.) */ - string_map_insert_nocopy (&view->render_opts, xstrdup ("paper-size"), + string_map_insert_nocopy (options, xstrdup ("paper-size"), xasprintf ("%dx1000000pt", view->render_width)); - string_map_insert (&view->render_opts, "left-margin", "0"); - string_map_insert (&view->render_opts, "right-margin", "0"); - string_map_insert (&view->render_opts, "top-margin", "0"); - string_map_insert (&view->render_opts, "bottom-margin", "0"); + string_map_insert (options, "left-margin", "0"); + string_map_insert (options, "right-margin", "0"); + string_map_insert (options, "top-margin", "0"); + string_map_insert (options, "bottom-margin", "0"); +} - view->xr = xr_driver_create (cr, &view->render_opts); +static void +create_xr (struct psppire_output_view *view) +{ + get_xr_options (view, &view->render_opts); - text_item = text_item_create (TEXT_ITEM_PARAGRAPH, "X"); - r = xr_rendering_create (view->xr, text_item_super (text_item), cr); - xr_rendering_measure (r, &font_width, &view->font_height); + struct string_map options; + string_map_clone (&options, &view->render_opts); + + GdkWindow *win = gtk_layout_get_bin_window (view->output); + cairo_region_t *region = gdk_window_get_visible_region (win); + GdkDrawingContext *ctx = gdk_window_begin_draw_frame (win, region); + cairo_t *cr = gdk_drawing_context_get_cairo_context (ctx); + + view->xr = xr_driver_create (cr, &options); + string_map_destroy (&options); + + struct text_item *text_item = text_item_create (TEXT_ITEM_LOG, "X"); + struct xr_rendering *r + = xr_rendering_create (view->xr, text_item_super (text_item), cr); + xr_rendering_measure (r, NULL, &view->font_height); + xr_rendering_destroy (r); text_item_unref (text_item); - cairo_destroy (cr); + gdk_window_end_draw_frame (win, ctx); + cairo_region_destroy (region); } /* Return the horizontal position to place a widget whose @@ -201,18 +201,6 @@ create_drawing_area (struct psppire_output_view *view, GtkWidget *drawing_area, struct xr_rendering *r, int tw, int th) { - /* Enable this to help with debugging. It shows you which widgets are being - put where. */ - if (0) - { - GdkRGBA green = {0, 1, 0, 1}; - gtk_widget_override_background_color (GTK_WIDGET (view->output), - GTK_STATE_FLAG_NORMAL, &green); - GdkRGBA red = {1, 0, 0, 1}; - gtk_widget_override_background_color (drawing_area, - GTK_STATE_FLAG_NORMAL, &red); - } - g_object_set_data_full (G_OBJECT (drawing_area), "rendering", r, free_rendering); @@ -232,14 +220,18 @@ rerender (struct psppire_output_view *view) { struct output_view_item *item; GdkWindow *gdkw = gtk_widget_get_window (GTK_WIDGET (view->output)); - cairo_t *cr; if (!view->n_items || ! gdkw) return; - cr = gdk_cairo_create (gdkw); if (view->xr == NULL) create_xr (view); + + GdkWindow *win = gtk_layout_get_bin_window (view->output); + cairo_region_t *region = gdk_window_get_visible_region (win); + GdkDrawingContext *ctx = gdk_window_begin_draw_frame (win, region); + cairo_t *cr = gdk_drawing_context_get_cairo_context (ctx); + view->y = 0; view->max_width = 0; for (item = view->items; item < &view->items[view->n_items]; item++) @@ -251,6 +243,9 @@ rerender (struct psppire_output_view *view) if (view->y > 0) view->y += view->font_height / 2; + if (is_group_open_item (item->item)) + continue; + r = xr_rendering_create (view->xr, item->item, cr); if (r == NULL) { @@ -301,7 +296,9 @@ rerender (struct psppire_output_view *view) gtk_layout_set_size (view->output, view->max_width + view->font_height, view->y + view->font_height); - cairo_destroy (cr); + + gdk_window_end_draw_frame (win, ctx); + cairo_region_destroy (region); } void @@ -310,21 +307,20 @@ psppire_output_view_put (struct psppire_output_view *view, { struct output_view_item *view_item; GtkWidget *drawing_area; - struct xr_rendering *r; struct string name; - GtkTreeStore *store; - cairo_t *cr = NULL; - GtkTreePath *path; - GtkTreeIter iter; int tw, th; if (is_group_close_item (item)) { - if (output_get_group_level () == 0) + if (view->cur_group) { - view->in_command = false; - return; + 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)) { @@ -341,51 +337,72 @@ psppire_output_view_put (struct psppire_output_view *view, view_item->item = output_item_ref (item); view_item->drawing_area = NULL; - if (gtk_widget_get_window (GTK_WIDGET (view->output))) + GdkWindow *win = gtk_widget_get_window (GTK_WIDGET (view->output)); + if (is_group_open_item (item)) + tw = th = 0; + else if (win) { view_item->drawing_area = drawing_area = gtk_drawing_area_new (); - cr = gdk_cairo_create (gtk_widget_get_window (GTK_WIDGET (view->output))); if (view->xr == NULL) create_xr (view); + cairo_region_t *region = gdk_window_get_visible_region (win); + GdkDrawingContext *ctx = gdk_window_begin_draw_frame (win, region); + cairo_t *cr = gdk_drawing_context_get_cairo_context (ctx); + if (view->y > 0) view->y += view->font_height / 2; - r = xr_rendering_create (view->xr, item, cr); + struct xr_rendering *r = xr_rendering_create (view->xr, item, cr); if (r == NULL) - goto done; + { + gdk_window_end_draw_frame (win, ctx); + cairo_region_destroy (region); + return; + } xr_rendering_measure (r, &tw, &th); create_drawing_area (view, drawing_area, r, tw, th); + gdk_window_end_draw_frame (win, ctx); + cairo_region_destroy (region); } else tw = th = 0; - if (view->overview - && (!is_text_item (item) - || text_item_get_type (to_text_item (item)) != TEXT_ITEM_SYNTAX - || !view->in_command)) + if (view->overview) { - store = GTK_TREE_STORE (gtk_tree_view_get_model (view->overview)); + GtkTreeStore *store = GTK_TREE_STORE ( + gtk_tree_view_get_model (view->overview)); ds_init_empty (&name); - if (is_group_open_item (item) && output_get_group_level () == 1) - { - gtk_tree_store_append (store, &iter, NULL); - view->cur_command = iter; /* XXX shouldn't save a GtkTreeIter */ - view->in_command = true; - } + + /* 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 + && gtk_tree_model_get_iter (GTK_TREE_MODEL (store), + &parent, view->cur_group)) + gtk_tree_store_append (store, &iter, &parent); else + gtk_tree_store_append (store, &iter, NULL); + + if (is_group_open_item (item)) { - GtkTreeIter *p = view->in_command ? &view->cur_command : NULL; - gtk_tree_store_append (store, &iter, p); + gtk_tree_path_free (view->cur_group); + view->cur_group = gtk_tree_model_get_path (GTK_TREE_MODEL (store), + &iter); } ds_clear (&name); if (is_text_item (item)) - ds_put_cstr (&name, text_item_get_text (to_text_item (item))); + { + const struct text_item *text_item = to_text_item (item); + ds_put_cstr (&name, text_item_type_to_string ( + text_item_get_type (text_item))); + } else if (is_message_item (item)) { const struct message_item *msg_item = to_message_item (item); @@ -419,7 +436,8 @@ psppire_output_view_put (struct psppire_output_view *view, -1); ds_destroy (&name); - path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter); + GtkTreePath *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); } @@ -429,9 +447,6 @@ psppire_output_view_put (struct psppire_output_view *view, view->y += th; gtk_layout_set_size (view->output, view->max_width, view->y); - -done: - cairo_destroy (cr); } static void @@ -469,10 +484,20 @@ on_style_updated (GtkWidget *toplevel, struct psppire_output_view *view) { if (!view->n_items || !gtk_widget_get_window (GTK_WIDGET (view->output))) return; - string_map_clear (&view->render_opts); - xr_driver_destroy (view->xr); - create_xr (view); - rerender (view); + + /* GTK+ fires this signal for trivial changes like the mouse moving in or out + of the window. Check whether the actual rendering options changed and + re-render only if they did. */ + struct string_map options = STRING_MAP_INITIALIZER (options); + get_xr_options (view, &options); + if (!string_map_equals (&options, &view->render_opts)) + { + xr_driver_destroy (view->xr); + view->xr = NULL; + + rerender (view); + } + string_map_destroy (&options); } enum { @@ -509,7 +534,7 @@ clipboard_get_cb (GtkClipboard *clipboard, GList *rows = gtk_tree_selection_get_selected_rows (sel, &model); GList *n = rows; - if ( n == NULL) + if (n == NULL) return; if (path_search (dirname, sizeof dirname, NULL, NULL, true) @@ -567,7 +592,7 @@ clipboard_get_cb (GtkClipboard *clipboard, n = n->next; } - if ( driver->class->flush) + if (driver->class->flush) driver->class->flush (driver); @@ -576,7 +601,7 @@ clipboard_get_cb (GtkClipboard *clipboard, output_driver_destroy (driver); driver = NULL; - if ( g_file_get_contents (filename, &text, &length, NULL) ) + if (g_file_get_contents (filename, &text, &length, NULL)) { gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data), 8, @@ -700,8 +725,7 @@ psppire_output_view_new (GtkLayout *output, GtkTreeView *overview) view->y = 0; string_map_init (&view->render_opts); view->overview = overview; - memset (&view->cur_command, 0, sizeof view->cur_command); - view->in_command = false; + view->cur_group = NULL; view->toplevel = gtk_widget_get_toplevel (GTK_WIDGET (output)); view->items = NULL; view->n_items = view->allocated_items = 0; @@ -769,6 +793,9 @@ psppire_output_view_destroy (struct psppire_output_view *view) xr_driver_destroy (view->xr); + if (view->cur_group) + gtk_tree_path_free (view->cur_group); + free (view); } @@ -878,7 +905,7 @@ paginate (GtkPrintOperation *operation, complete. Don't let that screw up printing. */ return TRUE; } - else if ( view->print_item < view->n_items ) + else if (view->print_item < view->n_items) { xr_driver_output_item (view->print_xrd, view->items[view->print_item++].item);