Add AgChartRenderer class
It is a subclass of GdkCellRendererPixbuf specialised in displaying Astrognome chart previews.
This commit is contained in:
		| @@ -40,6 +40,7 @@ PKG_CHECK_MODULES([GDA], [libgda-5.0 libgda-sqlite-5.0]) | ||||
| PKG_CHECK_MODULES([PIXBUF], [gdk-pixbuf-2.0]) | ||||
| PKG_CHECK_MODULES([RSVG], [librsvg-2.0]) | ||||
| PKG_CHECK_MODULES([SWE_GLIB], [swe-glib >= 2.1.0]) | ||||
| PKG_CHECK_MODULES([CAIRO], [cairo]); | ||||
|  | ||||
| LIBGD_INIT([ | ||||
|     main-view | ||||
|   | ||||
| @@ -20,6 +20,7 @@ astrognome_source_files = \ | ||||
| 						  ag-preferences.c    \ | ||||
| 						  ag-db.c             \ | ||||
| 						  ag-display-theme.c  \ | ||||
| 						  ag-chart-renderer.c \ | ||||
| 						  astrognome.c        \ | ||||
| 						  $(NULL) | ||||
|  | ||||
| @@ -32,9 +33,9 @@ AM_CPPFLAGS = -DG_LOG_DOMAIN=\"Astrognome\" -DLOCALEDIR=\"$(localedir)\" -DPKGDA | ||||
| bin_PROGRAMS = astrognome | ||||
|  | ||||
| astrognome_SOURCES = $(astrognome_source_files) $(BUILT_SOURCES) | ||||
| astrognome_LDADD = $(SWE_GLIB_LIBS) $(GTK_LIBS) $(LIBXML_LIBS) $(LIBXSLT_LIBS) $(WEBKIT_LIBS) $(GDA_LIBS) $(PIXBUF_LIBS) $(RSVG_LIBS) $(top_builddir)/libgd/libgd.la | ||||
| astrognome_LDADD = $(SWE_GLIB_LIBS) $(GTK_LIBS) $(LIBXML_LIBS) $(LIBXSLT_LIBS) $(WEBKIT_LIBS) $(GDA_LIBS) $(PIXBUF_LIBS) $(RSVG_LIBS) $(CAIRO_LIBS) $(top_builddir)/libgd/libgd.la | ||||
| astrognome_LDFLAGS = -rdynamic | ||||
| astrognome_CFLAGS = $(SWE_GLIB_CFLAGS) $(CFLAGS) $(GTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBXSLT_CFLAGS) $(WEBKIT_CFLAGS) $(GDA_CFLAGS) $(PIXBUF_CFLAGS) $(RSVG_CFLAGS) -Wall | ||||
| astrognome_CFLAGS = $(SWE_GLIB_CFLAGS) $(CFLAGS) $(GTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBXSLT_CFLAGS) $(WEBKIT_CFLAGS) $(GDA_CFLAGS) $(PIXBUF_CFLAGS) $(RSVG_CFLAGS) $(CAIRO_CFLAGS) -Wall | ||||
|  | ||||
| # The following two lines generate a .dir-locals.el file, so | ||||
| # company-mode won’t die due to unknown includes | ||||
|   | ||||
							
								
								
									
										305
									
								
								src/ag-chart-renderer.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										305
									
								
								src/ag-chart-renderer.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,305 @@ | ||||
| #include <cairo.h> | ||||
|  | ||||
| #include "ag-chart-renderer.h" | ||||
|  | ||||
| typedef struct { | ||||
|     gchar    *css_class; | ||||
|     gboolean checked; | ||||
|     gboolean toggle_visible; | ||||
| } AgChartRendererPrivate; | ||||
|  | ||||
| enum { | ||||
|     PROP_0, | ||||
|     AG_CHART_RENDERER_PROP_CSS_CLASS, | ||||
|     AG_CHART_RENDERER_PROP_CHECKED, | ||||
|     AG_CHART_RENDERER_PROP_TOGGLE_VISIBLE, | ||||
| }; | ||||
|  | ||||
| static void ag_chart_renderer_dispose(GObject *gobject); | ||||
| static void ag_chart_renderer_finalize(GObject *gobject); | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE(AgChartRenderer, ag_chart_renderer, GTK_TYPE_CELL_RENDERER_PIXBUF); | ||||
|  | ||||
| static void | ||||
| ag_chart_renderer_render(GtkCellRenderer      *renderer, | ||||
|                          cairo_t              *cr, | ||||
|                          GtkWidget            *widget, | ||||
|                          const GdkRectangle   *background_area, | ||||
|                          const GdkRectangle   *cell_area, | ||||
|                          GtkCellRendererState flags) | ||||
| { | ||||
|     AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private(AG_CHART_RENDERER(renderer)); | ||||
|     int             margin; | ||||
|     GtkStyleContext *context = gtk_widget_get_style_context(widget); | ||||
|     GdkPixbuf       *pixbuf; | ||||
|  | ||||
|     gtk_style_context_save(context); | ||||
|     gtk_style_context_add_class(context, "ag-chart-renderer"); | ||||
|  | ||||
|     if (priv->css_class) { | ||||
|         gtk_style_context_add_class(context, priv->css_class); | ||||
|     } | ||||
|  | ||||
|     cairo_save(cr); | ||||
|     gdk_cairo_rectangle(cr, cell_area); | ||||
|     cairo_clip(cr); | ||||
|  | ||||
|     cairo_translate(cr, cell_area->x, cell_area->y); | ||||
|  | ||||
|     margin = MAX(AG_CHART_RENDERER_TILE_MARGIN, (int)((cell_area->width - AG_CHART_RENDERER_TILE_SIZE) / 2)); | ||||
|  | ||||
|     g_object_get(renderer, "pixbuf", &pixbuf, NULL); | ||||
|  | ||||
|     if (pixbuf != NULL) { | ||||
|         GdkRectangle area = {margin, margin, AG_CHART_RENDERER_TILE_SIZE, AG_CHART_RENDERER_TILE_SIZE}; | ||||
|  | ||||
|         g_debug("Rendering chart with preview image"); | ||||
|  | ||||
|         GTK_CELL_RENDERER_CLASS(ag_chart_renderer_parent_class)->render(renderer, cr, widget, &area, &area, flags); | ||||
|     } else { | ||||
|         g_debug("Rendering chart without preview image"); | ||||
|  | ||||
|         gtk_render_frame(context, cr, margin, margin, AG_CHART_RENDERER_TILE_SIZE, AG_CHART_RENDERER_TILE_SIZE); | ||||
|         gtk_render_background(context, cr, margin, margin, AG_CHART_RENDERER_TILE_SIZE, AG_CHART_RENDERER_TILE_SIZE); | ||||
|     } | ||||
|  | ||||
|     gtk_style_context_restore(context); | ||||
|  | ||||
|     if (priv->toggle_visible) { | ||||
|         gint xpad, | ||||
|              ypad, | ||||
|              x_offset, | ||||
|              check_x, | ||||
|              check_y; | ||||
|  | ||||
|         gtk_cell_renderer_get_padding(GTK_CELL_RENDERER(renderer), &xpad, &ypad); | ||||
|  | ||||
|         if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL) { | ||||
|             x_offset = xpad; | ||||
|         } else { | ||||
|             x_offset = cell_area->width - AG_CHART_RENDERER_CHECK_ICON_SIZE - xpad; | ||||
|         } | ||||
|  | ||||
|         check_x = x_offset; | ||||
|         check_y = cell_area->height - AG_CHART_RENDERER_CHECK_ICON_SIZE - ypad; | ||||
|  | ||||
|         gtk_style_context_save(context); | ||||
|         gtk_style_context_add_class(context, GTK_STYLE_CLASS_CHECK); | ||||
|  | ||||
|         if (priv->checked) { | ||||
|             gtk_style_context_set_state(context, GTK_STATE_FLAG_CHECKED); | ||||
|         } | ||||
|  | ||||
|         gtk_render_background(context, cr, check_x, check_y, AG_CHART_RENDERER_CHECK_ICON_SIZE, AG_CHART_RENDERER_CHECK_ICON_SIZE); | ||||
|         gtk_render_frame(context, cr, check_x, check_y, AG_CHART_RENDERER_CHECK_ICON_SIZE, AG_CHART_RENDERER_CHECK_ICON_SIZE); | ||||
|         gtk_render_check(context, cr, check_x, check_y, AG_CHART_RENDERER_CHECK_ICON_SIZE, AG_CHART_RENDERER_CHECK_ICON_SIZE); | ||||
|  | ||||
|         gtk_style_context_restore(context); | ||||
|     } | ||||
|  | ||||
|     cairo_restore(cr); | ||||
| } | ||||
|  | ||||
| void | ||||
| ag_chart_renderer_set_css_class(AgChartRenderer *chart_renderer, const gchar *css_class) | ||||
| { | ||||
|     AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private(chart_renderer); | ||||
|  | ||||
|     g_free(priv->css_class); | ||||
|     priv->css_class = g_strdup(css_class); | ||||
| } | ||||
|  | ||||
| const gchar * | ||||
| ag_chart_renderer_get_css_class(AgChartRenderer *chart_renderer) | ||||
| { | ||||
|     AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private(chart_renderer); | ||||
|  | ||||
|     return priv->css_class; | ||||
| } | ||||
|  | ||||
| void | ||||
| ag_chart_renderer_set_checked(AgChartRenderer *chart_renderer, gboolean checked) | ||||
| { | ||||
|     AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private(chart_renderer); | ||||
|  | ||||
|     priv->checked = checked; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| ag_chart_renderer_get_checked(AgChartRenderer *chart_renderer) | ||||
| { | ||||
|     AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private(chart_renderer); | ||||
|  | ||||
|     return priv->checked; | ||||
| } | ||||
|  | ||||
| void | ||||
| ag_chart_renderer_set_toggle_visible(AgChartRenderer *chart_renderer, gboolean toggle_visible) | ||||
| { | ||||
|     AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private(chart_renderer); | ||||
|  | ||||
|     priv->toggle_visible = toggle_visible; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| ag_chart_renderer_get_toggle_visible(AgChartRenderer *chart_renderer) | ||||
| { | ||||
|     AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private(chart_renderer); | ||||
|  | ||||
|     return priv->toggle_visible; | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_chart_renderer_get_property(GObject    *gobject, | ||||
|                                guint      prop_id, | ||||
|                                GValue     *value, | ||||
|                                GParamSpec *pspec) | ||||
| { | ||||
|     AgChartRenderer *chart_renderer = AG_CHART_RENDERER(gobject); | ||||
|  | ||||
|     switch (prop_id) { | ||||
|         case AG_CHART_RENDERER_PROP_CSS_CLASS: | ||||
|             g_value_set_string(value, ag_chart_renderer_get_css_class(chart_renderer)); | ||||
|  | ||||
|             break; | ||||
|  | ||||
|         case AG_CHART_RENDERER_PROP_CHECKED: | ||||
|             g_value_set_boolean(value, ag_chart_renderer_get_checked(chart_renderer)); | ||||
|  | ||||
|             break; | ||||
|  | ||||
|         case AG_CHART_RENDERER_PROP_TOGGLE_VISIBLE: | ||||
|             g_value_set_boolean(value, ag_chart_renderer_get_toggle_visible(chart_renderer)); | ||||
|  | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); | ||||
|  | ||||
|             break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_chart_renderer_set_property(GObject      *gobject, | ||||
|                                guint        prop_id, | ||||
|                                const GValue *value, | ||||
|                                GParamSpec   *pspec) | ||||
| { | ||||
|     AgChartRenderer *chart_renderer = AG_CHART_RENDERER(gobject); | ||||
|  | ||||
|     switch (prop_id) { | ||||
|         case AG_CHART_RENDERER_PROP_CSS_CLASS: | ||||
|             ag_chart_renderer_set_css_class(chart_renderer, g_value_get_string(value)); | ||||
|  | ||||
|             break; | ||||
|  | ||||
|         case AG_CHART_RENDERER_PROP_CHECKED: | ||||
|             ag_chart_renderer_set_checked(chart_renderer, g_value_get_boolean(value)); | ||||
|  | ||||
|             break; | ||||
|  | ||||
|         case AG_CHART_RENDERER_PROP_TOGGLE_VISIBLE: | ||||
|             ag_chart_renderer_set_toggle_visible(chart_renderer, g_value_get_boolean(value)); | ||||
|  | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); | ||||
|  | ||||
|             break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_chart_renderer_class_init(AgChartRendererClass *klass) | ||||
| { | ||||
|     GObjectClass         *gobject_class       = (GObjectClass *)klass; | ||||
|     GtkCellRendererClass *cell_renderer_class = (GtkCellRendererClass *)klass; | ||||
|  | ||||
|     gobject_class->dispose      = ag_chart_renderer_dispose; | ||||
|     gobject_class->finalize     = ag_chart_renderer_finalize; | ||||
|     gobject_class->set_property = ag_chart_renderer_set_property; | ||||
|     gobject_class->get_property = ag_chart_renderer_get_property; | ||||
|     cell_renderer_class->render = ag_chart_renderer_render; | ||||
|  | ||||
|     g_object_class_install_property( | ||||
|             G_OBJECT_CLASS(klass), | ||||
|             AG_CHART_RENDERER_PROP_CSS_CLASS, | ||||
|             g_param_spec_string( | ||||
|                     "css-class", | ||||
|                     "css-class", | ||||
|                     "CSS Class", | ||||
|                     NULL, | ||||
|                     G_PARAM_STATIC_NAME | ||||
|                     | G_PARAM_STATIC_NICK | ||||
|                     | G_PARAM_STATIC_BLURB | ||||
|                     | G_PARAM_READABLE | ||||
|                     | G_PARAM_WRITABLE | ||||
|                 ) | ||||
|         ); | ||||
|  | ||||
|     g_object_class_install_property( | ||||
|             G_OBJECT_CLASS(klass), | ||||
|             AG_CHART_RENDERER_PROP_CHECKED, | ||||
|             g_param_spec_boolean( | ||||
|                     "checked", | ||||
|                     "checked", | ||||
|                     "Checked", | ||||
|                     FALSE, | ||||
|                     G_PARAM_STATIC_NAME | ||||
|                     | G_PARAM_STATIC_NICK | ||||
|                     | G_PARAM_STATIC_BLURB | ||||
|                     | G_PARAM_READABLE | ||||
|                     | G_PARAM_WRITABLE | ||||
|                 ) | ||||
|         ); | ||||
|  | ||||
|     g_object_class_install_property( | ||||
|             G_OBJECT_CLASS(klass), | ||||
|             AG_CHART_RENDERER_PROP_TOGGLE_VISIBLE, | ||||
|             g_param_spec_boolean( | ||||
|                     "toggle-visible", | ||||
|                     "toggle-visible", | ||||
|                     "Toggle visible", | ||||
|                     FALSE, | ||||
|                     G_PARAM_STATIC_NAME | ||||
|                     | G_PARAM_STATIC_NICK | ||||
|                     | G_PARAM_STATIC_BLURB | ||||
|                     | G_PARAM_READABLE | ||||
|                     | G_PARAM_WRITABLE | ||||
|                 ) | ||||
|         ); | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_chart_renderer_init(AgChartRenderer *chart_renderer) | ||||
| { | ||||
|     AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private(chart_renderer); | ||||
|  | ||||
|     priv->checked = FALSE; | ||||
|     priv->toggle_visible = FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_chart_renderer_dispose(GObject *gobject) | ||||
| { | ||||
|     G_OBJECT_CLASS(ag_chart_renderer_parent_class)->dispose(gobject); | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_chart_renderer_finalize (GObject *gobject) | ||||
| { | ||||
|     g_signal_handlers_destroy(gobject); | ||||
|     G_OBJECT_CLASS(ag_chart_renderer_parent_class)->finalize(gobject); | ||||
| } | ||||
|  | ||||
| AgChartRenderer * | ||||
| ag_chart_renderer_new(void) | ||||
| { | ||||
|     AgChartRenderer *chart_renderer = NULL; | ||||
|  | ||||
|     chart_renderer = g_object_new(AG_TYPE_CHART_RENDERER, NULL); | ||||
|  | ||||
|     return chart_renderer; | ||||
| } | ||||
							
								
								
									
										58
									
								
								src/ag-chart-renderer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/ag-chart-renderer.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| #ifndef __AG_CHART_RENDERER_H__ | ||||
| #define __AG_CHART_RENDERER_H__ | ||||
|  | ||||
| #include <gtk/gtk.h> | ||||
|  | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define AG_TYPE_CHART_RENDERER                                          \ | ||||
|    (ag_chart_renderer_get_type()) | ||||
| #define AG_CHART_RENDERER(obj)                                          \ | ||||
|    (G_TYPE_CHECK_INSTANCE_CAST ((obj),                                  \ | ||||
|                                 AG_TYPE_CHART_RENDERER,                 \ | ||||
|                                 AgChartRenderer)) | ||||
| #define AG_CHART_RENDERER_CLASS(klass)                                  \ | ||||
|    (G_TYPE_CHECK_CLASS_CAST ((klass),                                   \ | ||||
|                              AG_TYPE_CHART_RENDERER,                    \ | ||||
|                              AgChartRendererClass)) | ||||
| #define IS_AG_CHART_RENDERER(obj)                                       \ | ||||
|    (G_TYPE_CHECK_INSTANCE_TYPE ((obj),                                  \ | ||||
|                                 AG_TYPE_CHART_RENDERER)) | ||||
| #define IS_AG_CHART_RENDERER_CLASS(klass)                               \ | ||||
|    (G_TYPE_CHECK_CLASS_TYPE ((klass),                                   \ | ||||
|                              AG_TYPE_CHART_RENDERER)) | ||||
| #define AG_CHART_RENDERER_GET_CLASS(obj)                                \ | ||||
|    (G_TYPE_INSTANCE_GET_CLASS ((obj),                                   \ | ||||
|                                AG_TYPE_CHART_RENDERER,                  \ | ||||
|                                AgChartRendererClass)) | ||||
|  | ||||
| typedef struct _AgChartRenderer      AgChartRenderer; | ||||
| typedef struct _AgChartRendererClass AgChartRendererClass; | ||||
|  | ||||
| struct _AgChartRendererClass | ||||
| { | ||||
|     GtkCellRendererPixbufClass parent_class; | ||||
| }; | ||||
|  | ||||
| struct _AgChartRenderer | ||||
| { | ||||
|     GtkCellRendererPixbuf parent; | ||||
| }; | ||||
|  | ||||
| #define AG_CHART_RENDERER_TILE_SIZE 256 | ||||
| #define AG_CHART_RENDERER_CHECK_ICON_SIZE 40 | ||||
| #define AG_CHART_RENDERER_TILE_MARGIN AG_CHART_RENDERER_CHECK_ICON_SIZE / 4 | ||||
| #define AG_CHART_RENDERER_TILE_MARGIN_BOTTOM AG_CHART_RENDERER_CHECK_ICON_SIZE / 8 | ||||
|  | ||||
| GType ag_chart_renderer_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| AgChartRenderer *ag_chart_renderer_new(void); | ||||
|  | ||||
| void ag_chart_renderer_set_toggle_visible(AgChartRenderer *chart_renderer, gboolean toggle_visible); | ||||
|  | ||||
| gboolean ag_chart_renderer_get_toggle_visible(AgChartRenderer *chart_renderer); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __AG_CHART_RENDERER_H__ */ | ||||
		Reference in New Issue
	
	Block a user