From 81dece3642da9bdcbdec4aa09b0c2008c86d6161 Mon Sep 17 00:00:00 2001 From: Friedrich Beckmann Date: Tue, 8 Sep 2020 23:48:08 +0200 Subject: [PATCH] output view: make items selectable and use system colours The items in the output window are now selectable and the rendering uses the gtk3 style context for background and default foreground colours. --- src/output/cairo.c | 72 +++++++++++++++++++------------- src/ui/gui/psppire-output-view.c | 63 ++++++++++++++++++++++++---- 2 files changed, 97 insertions(+), 38 deletions(-) diff --git a/src/output/cairo.c b/src/output/cairo.c index bcb995c68c..8c67ce03ae 100644 --- a/src/output/cairo.c +++ b/src/output/cairo.c @@ -156,6 +156,8 @@ struct xr_driver struct cell_color bg; /* Background color */ struct cell_color fg; /* Foreground color */ + bool transparent; /* true -> do not render background */ + bool systemcolors; /* true -> do not change colors */ int initial_page_number; @@ -565,6 +567,9 @@ apply_options (struct xr_driver *xr, struct string_map *o) parse_color (d, o, "background-color", "#FFFFFFFFFFFF", &xr->bg); parse_color (d, o, "foreground-color", "#000000000000", &xr->fg); + xr->transparent = parse_boolean (opt (d, o, "transparent", "false")); + xr->systemcolors = parse_boolean (opt (d, o, "systemcolors", "false")); + /* Get dimensions. */ parse_paper_size (opt (d, o, "paper-size", ""), &paper_width, &paper_length); left_margin = parse_dimension (opt (d, o, "left-margin", ".5in")); @@ -806,8 +811,9 @@ xr_set_cairo (struct xr_driver *xr, cairo_t *cairo) xr->params->rtl = render_direction_rtl (); } - cairo_set_source_rgb (xr->cairo, - xr->fg.r / 255.0, xr->fg.g / 255.0, xr->fg.b / 255.0); + if (!xr->systemcolors) + cairo_set_source_rgb (xr->cairo, + xr->fg.r / 255.0, xr->fg.g / 255.0, xr->fg.b / 255.0); } static struct output_driver * @@ -1004,13 +1010,15 @@ xr_submit (struct output_driver *driver, const struct output_item *output_item) void xr_driver_next_page (struct xr_driver *xr, cairo_t *cairo) { - cairo_save (cairo); - cairo_set_source_rgb (cairo, - xr->bg.r / 255.0, xr->bg.g / 255.0, xr->bg.b / 255.0); - cairo_rectangle (cairo, 0, 0, xr->width, xr->length); - cairo_fill (cairo); - cairo_restore (cairo); - + if (!xr->transparent) + { + cairo_save (cairo); + cairo_set_source_rgb (cairo, + xr->bg.r / 255.0, xr->bg.g / 255.0, xr->bg.b / 255.0); + cairo_rectangle (cairo, 0, 0, xr->width, xr->length); + cairo_fill (cairo); + cairo_restore (cairo); + } cairo_translate (cairo, xr_to_pt (xr->left_margin), xr_to_pt (xr->top_margin + xr->headings_height[0])); @@ -1092,7 +1100,8 @@ dump_line (struct xr_driver *xr, int x0, int y0, int x1, int y1, int style, const struct cell_color *color) { cairo_new_path (xr->cairo); - set_source_rgba (xr->cairo, color); + if (!xr->systemcolors) + set_source_rgba (xr->cairo, color); cairo_set_line_width ( xr->cairo, xr_to_pt (style == RENDER_LINE_THICK ? XR_LINE_WIDTH * 2 @@ -1356,29 +1365,32 @@ xr_draw_cell (void *xr_, const struct table_cell *cell, int color_idx, struct xr_driver *xr = xr_; int w, h, brk; - cairo_save (xr->cairo); - int bg_clip[TABLE_N_AXES][2]; - for (int axis = 0; axis < TABLE_N_AXES; axis++) + if (!xr->transparent) { - bg_clip[axis][0] = clip[axis][0]; - if (bb[axis][0] == clip[axis][0]) - bg_clip[axis][0] -= spill[axis][0]; - - bg_clip[axis][1] = clip[axis][1]; - if (bb[axis][1] == clip[axis][1]) - bg_clip[axis][1] += spill[axis][1]; + cairo_save (xr->cairo); + int bg_clip[TABLE_N_AXES][2]; + for (int axis = 0; axis < TABLE_N_AXES; axis++) + { + bg_clip[axis][0] = clip[axis][0]; + if (bb[axis][0] == clip[axis][0]) + bg_clip[axis][0] -= spill[axis][0]; + + bg_clip[axis][1] = clip[axis][1]; + if (bb[axis][1] == clip[axis][1]) + bg_clip[axis][1] += spill[axis][1]; + } + xr_clip (xr, bg_clip); + set_source_rgba (xr->cairo, &cell->style->font_style.bg[color_idx]); + fill_rectangle (xr, + bb[H][0] - spill[H][0], + bb[V][0] - spill[V][0], + bb[H][1] + spill[H][1], + bb[V][1] + spill[V][1]); + cairo_restore (xr->cairo); } - xr_clip (xr, bg_clip); - set_source_rgba (xr->cairo, &cell->style->font_style.bg[color_idx]); - fill_rectangle (xr, - bb[H][0] - spill[H][0], - bb[V][0] - spill[V][0], - bb[H][1] + spill[H][1], - bb[V][1] + spill[V][1]); - cairo_restore (xr->cairo); - cairo_save (xr->cairo); - set_source_rgba (xr->cairo, &cell->style->font_style.fg[color_idx]); + if (!xr->systemcolors) + set_source_rgba (xr->cairo, &cell->style->font_style.fg[color_idx]); for (int axis = 0; axis < TABLE_N_AXES; axis++) { diff --git a/src/ui/gui/psppire-output-view.c b/src/ui/gui/psppire-output-view.c index 58454acbe5..490f3de70c 100644 --- a/src/ui/gui/psppire-output-view.c +++ b/src/ui/gui/psppire-output-view.c @@ -88,16 +88,10 @@ enum static gboolean layout_draw_callback (GtkWidget *widget, cairo_t *cr, gpointer data) { - cairo_save (cr); - int width = gtk_widget_get_allocated_width (widget); int height = gtk_widget_get_allocated_height (widget); - cairo_rectangle (cr, 0, 0, width, height); - cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); - cairo_fill (cr); - - cairo_restore (cr); - + GtkStyleContext *context = gtk_widget_get_style_context (widget); + gtk_render_background (context, cr, 0, 0, width, height); return FALSE; /* Continue drawing the GtkDrawingAreas. */ } @@ -109,8 +103,22 @@ draw_callback (GtkWidget *widget, cairo_t *cr, gpointer data) return TRUE; struct xr_rendering *r = g_object_get_data (G_OBJECT (widget), "rendering"); + + /* Draw the background based on the state of the widget + which can be selected or not selected */ + GtkStyleContext *context = gtk_widget_get_style_context (widget); + gtk_render_background (context, cr, clip.x, clip.y, + clip.x + clip.width, clip.y + clip.height); + + /* Select the default foreground color based on current style + and state of the widget */ + GtkStateFlags state = gtk_widget_get_state_flags (widget); + GdkRGBA color; + gtk_style_context_get_color (context, state, &color); + cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha); xr_rendering_draw (r, cr, clip.x, clip.y, clip.x + clip.width, clip.y + clip.height); + return TRUE; } @@ -196,6 +204,34 @@ get_xpos (const struct psppire_output_view *view, gint child_width) return (gtk_widget_get_direction (GTK_WIDGET (view->output)) == GTK_TEXT_DIR_RTL) ? w - child_width - gutter: gutter; } +static void +clear_selection (struct psppire_output_view *view) +{ + struct output_view_item *item = NULL; + if (view == NULL) + return; + if (view->items == NULL) + return; + + for (item = view->items; item < &view->items[view->n_items]; item++) + { + GtkWidget *widget = GTK_WIDGET (item->drawing_area); + if GTK_IS_WIDGET (widget) + gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_SELECTED); + } +} + +static gboolean +button_press_event_cb (GtkWidget *widget, + GdkEventButton *event, + struct psppire_output_view *view) +{ + clear_selection (view); + gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_SELECTED, FALSE); + gtk_widget_queue_draw (widget); + return TRUE; /* We have handled the event */ +} + static void create_drawing_area (struct psppire_output_view *view, GtkWidget *drawing_area, struct xr_rendering *r, @@ -204,6 +240,12 @@ create_drawing_area (struct psppire_output_view *view, g_object_set_data_full (G_OBJECT (drawing_area), "rendering", r, free_rendering); + g_signal_connect (drawing_area, "button-press-event", + G_CALLBACK (button_press_event_cb), view); + gtk_widget_add_events (drawing_area, GDK_BUTTON_PRESS_MASK); + GtkStyleContext *context = gtk_widget_get_style_context (drawing_area); + gtk_style_context_add_class (context, + GTK_STYLE_CLASS_VIEW); g_signal_connect (drawing_area, "draw", G_CALLBACK (draw_callback), view); @@ -301,6 +343,7 @@ rerender (struct psppire_output_view *view) cairo_region_destroy (region); } + void psppire_output_view_put (struct psppire_output_view *view, const struct output_item *item) @@ -364,6 +407,10 @@ psppire_output_view_put (struct psppire_output_view *view, xr_rendering_measure (r, &tw, &th); + struct string_map options = STRING_MAP_INITIALIZER (options); + string_map_insert (&options, "transparent", "true"); + string_map_insert (&options, "systemcolors", "true"); + xr_rendering_apply_options (r, &options); create_drawing_area (view, drawing_area, r, tw, th); gdk_window_end_draw_frame (win, ctx); cairo_region_destroy (region); -- 2.30.2