output view: make items selectable and use system colours
authorFriedrich Beckmann <friedrich.beckmann@gmx.de>
Tue, 8 Sep 2020 21:48:08 +0000 (23:48 +0200)
committerFriedrich Beckmann <friedrich.beckmann@gmx.de>
Fri, 11 Sep 2020 21:10:22 +0000 (23:10 +0200)
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
src/ui/gui/psppire-output-view.c

index bcb995c68c587ee2116d6b86458e9ecfc3b1e8f8..8c67ce03ae479a8d8ad0373f8ed35306822c9338 100644 (file)
@@ -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++)
     {
index 58454acbe5933aeb232ea0000841fba78fbd0f0f..490f3de70c1d2de72188f4e09706800ec489d15a 100644 (file)
@@ -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);