From: Matthias Clasen Date: Fri, 7 Oct 2022 03:03:15 +0000 (-0400) Subject: inspector: Stop using GtkTreeView for statistics X-Git-Tag: archive/raspbian/4.12.3+ds-1+rpi1~1^2^2^2~22^2~9^2~196^2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=61393fdcce48e0e46f482f3fe6470545111eeaa3;p=gtk4.git inspector: Stop using GtkTreeView for statistics GtkTreeView is heading towards deprecation; use a GtkColumnView instead. --- diff --git a/gtk/inspector/cellrenderergraph.c b/gtk/inspector/cellrenderergraph.c deleted file mode 100644 index 0aa65a0bb1..0000000000 --- a/gtk/inspector/cellrenderergraph.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (c) 2014 Benjamin Otte - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - */ - -#include "config.h" - -#include "cellrenderergraph.h" - -#include "graphdata.h" - -#include "gtksnapshot.h" -#include "gtkstylecontext.h" - -enum { - PROP_0, - PROP_DATA, - PROP_MINIMUM, - PROP_MAXIMUM -}; - -struct _GtkCellRendererGraphPrivate -{ - GtkGraphData *data; - double minimum; - double maximum; -}; - -G_DEFINE_TYPE_WITH_PRIVATE (GtkCellRendererGraph, gtk_cell_renderer_graph, GTK_TYPE_CELL_RENDERER) - -static void -gtk_cell_renderer_graph_dispose (GObject *object) -{ - GtkCellRendererGraph *graph = GTK_CELL_RENDERER_GRAPH (object); - GtkCellRendererGraphPrivate *priv = graph->priv; - - g_clear_object (&priv->data); - - G_OBJECT_CLASS (gtk_cell_renderer_graph_parent_class)->dispose (object); -} - -static void -gtk_cell_renderer_graph_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - GtkCellRendererGraph *cell = GTK_CELL_RENDERER_GRAPH (object); - GtkCellRendererGraphPrivate *priv = cell->priv; - - switch (param_id) - { - case PROP_DATA: - g_value_set_object (value, priv->data); - break; - case PROP_MINIMUM: - g_value_set_double (value, priv->minimum); - break; - case PROP_MAXIMUM: - g_value_set_double (value, priv->maximum); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - } -} - -static void -gtk_cell_renderer_graph_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - GtkCellRendererGraph *cell = GTK_CELL_RENDERER_GRAPH (object); - GtkCellRendererGraphPrivate *priv = cell->priv; - - switch (param_id) - { - case PROP_DATA: - if (priv->data != g_value_get_object (value)) - { - if (priv->data) - g_object_unref (priv->data); - priv->data = g_value_dup_object (value); - g_object_notify_by_pspec (object, pspec); - } - break; - case PROP_MINIMUM: - if (priv->minimum != g_value_get_double (value)) - { - priv->minimum = g_value_get_double (value); - g_object_notify_by_pspec (object, pspec); - } - break; - case PROP_MAXIMUM: - if (priv->maximum != g_value_get_double (value)) - { - priv->maximum = g_value_get_double (value); - g_object_notify_by_pspec (object, pspec); - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - } -} - -#define MIN_HEIGHT 24 -#define MIN_WIDTH (3 * MIN_HEIGHT) - -static void -gtk_cell_renderer_graph_get_preferred_width (GtkCellRenderer *cell, - GtkWidget *widget, - int *minimum, - int *natural) -{ - int xpad, size; - - g_object_get (cell, "xpad", &xpad, NULL); - - size = MIN_WIDTH + 2 * xpad; - - if (minimum != NULL) - *minimum = size; - if (natural != NULL) - *natural = size; -} - -static void -gtk_cell_renderer_graph_get_preferred_height (GtkCellRenderer *cell, - GtkWidget *widget, - int *minimum, - int *natural) -{ - int ypad, size; - - g_object_get (cell, "ypad", &ypad, NULL); - - size = MIN_HEIGHT + 2 * ypad; - - if (minimum != NULL) - *minimum = size; - if (natural != NULL) - *natural = size; -} - -static void -gtk_cell_renderer_graph_snapshot (GtkCellRenderer *cell, - GtkSnapshot *snapshot, - GtkWidget *widget, - const GdkRectangle *background_area, - const GdkRectangle *cell_area, - GtkCellRendererState flags) -{ - GtkCellRendererGraph *graph = GTK_CELL_RENDERER_GRAPH (cell); - GtkCellRendererGraphPrivate *priv = graph->priv; - GtkStyleContext *context; - double minimum, maximum, diff; - double x, y, width, height; - int xpad, ypad; - cairo_t *cr; - GdkRGBA color; - guint i, n; - -#define LINE_WIDTH 1.0 - - if (priv->data == NULL) - return; - - g_object_get (cell, - "xpad", &xpad, - "ypad", &ypad, - NULL); - - if (priv->minimum == -G_MAXDOUBLE) - minimum = gtk_graph_data_get_minimum (priv->data); - else - minimum = priv->minimum; - - if (priv->maximum == G_MAXDOUBLE) - maximum = gtk_graph_data_get_maximum (priv->data); - else - maximum = priv->maximum; - - diff = maximum - minimum; - - context = gtk_widget_get_style_context (widget); - gtk_style_context_get_color (context, &color); - - cr = gtk_snapshot_append_cairo (snapshot, - &GRAPHENE_RECT_INIT ( - background_area->x, background_area->y, - background_area->width, background_area->height - )); - - cairo_set_line_width (cr, 1.0); - - x = background_area->x + xpad + LINE_WIDTH / 2.0; - y = background_area->y + ypad + LINE_WIDTH / 2.0; - width = background_area->width - 2 * xpad - LINE_WIDTH; - height = background_area->height - 2 * ypad - LINE_WIDTH; - - cairo_move_to (cr, x, y + height); - - if (diff > 0) - { - n = gtk_graph_data_get_n_values (priv->data); - for (i = 0; i < n; i++) - { - double val = gtk_graph_data_get_value (priv->data, i); - - val = (val - minimum) / diff; - val = y + height - val * height; - - cairo_line_to (cr, x + width * i / (n - 1), val); - } - } - - cairo_line_to (cr, x + width, y + height); - cairo_close_path (cr); - - gdk_cairo_set_source_rgba (cr, &color); - cairo_stroke_preserve (cr); - - color.alpha *= 0.2; - gdk_cairo_set_source_rgba (cr, &color); - cairo_fill (cr); - - cairo_destroy (cr); -} - -static void -gtk_cell_renderer_graph_class_init (GtkCellRendererGraphClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass); - - object_class->dispose = gtk_cell_renderer_graph_dispose; - object_class->get_property = gtk_cell_renderer_graph_get_property; - object_class->set_property = gtk_cell_renderer_graph_set_property; - - cell_class->get_preferred_width = gtk_cell_renderer_graph_get_preferred_width; - cell_class->get_preferred_height = gtk_cell_renderer_graph_get_preferred_height; - cell_class->snapshot = gtk_cell_renderer_graph_snapshot; - - g_object_class_install_property (object_class, - PROP_DATA, - g_param_spec_object ("data", NULL, NULL, - GTK_TYPE_GRAPH_DATA, - G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); - - g_object_class_install_property (object_class, - PROP_MINIMUM, - g_param_spec_double ("minimum", NULL, NULL, - -G_MAXDOUBLE, G_MAXDOUBLE, -G_MAXDOUBLE, - G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); - - g_object_class_install_property (object_class, - PROP_MINIMUM, - g_param_spec_double ("maximum", NULL, NULL, - -G_MAXDOUBLE, G_MAXDOUBLE, G_MAXDOUBLE, - G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); -} - -static void -gtk_cell_renderer_graph_init (GtkCellRendererGraph *cell) -{ - cell->priv = gtk_cell_renderer_graph_get_instance_private (cell); - - cell->priv->minimum = -G_MAXDOUBLE; - cell->priv->maximum = G_MAXDOUBLE; -} - -GtkCellRenderer * -gtk_cell_renderer_graph_new (void) -{ - return g_object_new (GTK_TYPE_CELL_RENDERER_GRAPH, NULL); -} diff --git a/gtk/inspector/cellrenderergraph.h b/gtk/inspector/cellrenderergraph.h deleted file mode 100644 index 07e7a81bec..0000000000 --- a/gtk/inspector/cellrenderergraph.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2014 Benjamin Otte - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - */ - -#ifndef __GTK_CELL_RENDERER_GRAPH_H__ -#define __GTK_CELL_RENDERER_GRAPH_H__ - -#include - -G_BEGIN_DECLS - -#define GTK_TYPE_CELL_RENDERER_GRAPH (gtk_cell_renderer_graph_get_type ()) -#define GTK_CELL_RENDERER_GRAPH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CELL_RENDERER_GRAPH, GtkCellRendererGraph)) -#define GTK_CELL_RENDERER_GRAPH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_CELL_RENDERER_GRAPH, GtkCellRendererGraphClass)) -#define GTK_IS_CELL_RENDERER_GRAPH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_CELL_RENDERER_GRAPH)) -#define GTK_IS_CELL_RENDERER_GRAPH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CELL_RENDERER_GRAPH)) -#define GTK_CELL_RENDERER_GRAPH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CELL_RENDERER_GRAPH, GtkCellRendererGraphClass)) - -typedef struct _GtkCellRendererGraph GtkCellRendererGraph; -typedef struct _GtkCellRendererGraphClass GtkCellRendererGraphClass; -typedef struct _GtkCellRendererGraphPrivate GtkCellRendererGraphPrivate; - -struct _GtkCellRendererGraph -{ - GtkCellRenderer parent; - - /*< private >*/ - GtkCellRendererGraphPrivate *priv; -}; - -struct _GtkCellRendererGraphClass -{ - GtkCellRendererClass parent_class; - - /* Padding for future expansion */ - void (*_gtk_reserved1) (void); - void (*_gtk_reserved2) (void); - void (*_gtk_reserved3) (void); - void (*_gtk_reserved4) (void); -}; - -GDK_AVAILABLE_IN_ALL -GType gtk_cell_renderer_graph_get_type (void) G_GNUC_CONST; -GDK_AVAILABLE_IN_ALL -GtkCellRenderer *gtk_cell_renderer_graph_new (void); - -G_END_DECLS - -#endif /* __GTK_CELL_RENDERER_GRAPH_H__ */ diff --git a/gtk/inspector/graphdata.c b/gtk/inspector/graphdata.c index c546e148af..9fab32110f 100644 --- a/gtk/inspector/graphdata.c +++ b/gtk/inspector/graphdata.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Benjamin Otte + * Copyright (c) 2014 Benjamin Otte * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,74 +24,73 @@ enum { PROP_N_VALUES }; -struct _GtkGraphDataPrivate +struct _GraphData { + GObject parent; + guint n_values; guint offset; double *values; }; -G_DEFINE_TYPE_WITH_PRIVATE (GtkGraphData, gtk_graph_data, G_TYPE_OBJECT) +G_DEFINE_TYPE (GraphData, graph_data, G_TYPE_OBJECT) static void -gtk_graph_data_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) +graph_data_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) { - GtkGraphData *graph = GTK_GRAPH_DATA (object); - GtkGraphDataPrivate *priv = graph->priv; + GraphData *graph = GRAPH_DATA (object); switch (param_id) { - case PROP_N_VALUES: - g_value_set_boolean (value, priv->n_values); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + case PROP_N_VALUES: + g_value_set_boolean (value, graph->n_values); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); } } static void -gtk_graph_data_finalize (GObject *object) +graph_data_finalize (GObject *object) { - GtkGraphData *graph = GTK_GRAPH_DATA (object); - GtkGraphDataPrivate *priv = graph->priv; + GraphData *graph = GRAPH_DATA (object); - g_free (priv->values); + g_free (graph->values); - G_OBJECT_CLASS (gtk_graph_data_parent_class)->finalize (object); + G_OBJECT_CLASS (graph_data_parent_class)->finalize (object); } static void -gtk_graph_data_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) +graph_data_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) { - GtkGraphData *graph = GTK_GRAPH_DATA (object); - GtkGraphDataPrivate *priv = graph->priv; + GraphData *graph = GRAPH_DATA (object); switch (param_id) { - case PROP_N_VALUES: - priv->n_values = g_value_get_uint (value); - priv->values = g_new0 (double, priv->n_values); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + case PROP_N_VALUES: + graph->n_values = g_value_get_uint (value); + graph->values = g_new0 (double, graph->n_values); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); } } static void -gtk_graph_data_class_init (GtkGraphDataClass *klass) +graph_data_class_init (GraphDataClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->finalize = gtk_graph_data_finalize; - object_class->get_property = gtk_graph_data_get_property; - object_class->set_property = gtk_graph_data_set_property; + object_class->finalize = graph_data_finalize; + object_class->get_property = graph_data_get_property; + object_class->set_property = graph_data_set_property; g_object_class_install_property (object_class, PROP_N_VALUES, @@ -101,71 +100,63 @@ gtk_graph_data_class_init (GtkGraphDataClass *klass) } static void -gtk_graph_data_init (GtkGraphData *graph) +graph_data_init (GraphData *graph) { - graph->priv = gtk_graph_data_get_instance_private (graph); } -GtkGraphData * -gtk_graph_data_new (guint n_values) +GraphData * +graph_data_new (guint n_values) { - return g_object_new (GTK_TYPE_GRAPH_DATA, + return g_object_new (graph_data_get_type (), "n-values", n_values, NULL); } guint -gtk_graph_data_get_n_values (GtkGraphData *data) +graph_data_get_n_values (GraphData *data) { - return data->priv->n_values; + return data->n_values; } double -gtk_graph_data_get_value (GtkGraphData *data, - guint i) +graph_data_get_value (GraphData *data, + guint i) { - GtkGraphDataPrivate *priv = data->priv; - - return priv->values[(priv->offset + i) % priv->n_values]; + return data->values[(data->offset + i) % data->n_values]; } double -gtk_graph_data_get_minimum (GtkGraphData *data) +graph_data_get_minimum (GraphData *data) { - GtkGraphDataPrivate *priv = data->priv; double minimum = G_MAXDOUBLE; guint i; - for (i = 0; i < priv->n_values; i++) + for (i = 0; i < data->n_values; i++) { - minimum = MIN (minimum, priv->values[i]); + minimum = MIN (minimum, data->values[i]); } return minimum; } double -gtk_graph_data_get_maximum (GtkGraphData *data) +graph_data_get_maximum (GraphData *data) { - GtkGraphDataPrivate *priv = data->priv; double maximum = -G_MAXDOUBLE; guint i; - for (i = 0; i < priv->n_values; i++) + for (i = 0; i < data->n_values; i++) { - maximum = MAX (maximum, priv->values[i]); + maximum = MAX (maximum, data->values[i]); } return maximum; } void -gtk_graph_data_prepend_value (GtkGraphData *data, - double value) +graph_data_prepend_value (GraphData *data, + double value) { - GtkGraphDataPrivate *priv = data->priv; - - priv->offset = (priv->offset + priv->n_values - 1) % priv->n_values; - priv->values[priv->offset] = value; + data->offset = (data->offset + data->n_values - 1) % data->n_values; + data->values[data->offset] = value; } - diff --git a/gtk/inspector/graphdata.h b/gtk/inspector/graphdata.h index ee49009198..d746b018d0 100644 --- a/gtk/inspector/graphdata.h +++ b/gtk/inspector/graphdata.h @@ -15,57 +15,28 @@ * License along with this library. If not, see . */ -#ifndef __GTK_GRAPH_DATA_H__ -#define __GTK_GRAPH_DATA_H__ +#ifndef __GRAPH_DATA_H__ +#define __GRAPH_DATA_H__ #include G_BEGIN_DECLS -#define GTK_TYPE_GRAPH_DATA (gtk_graph_data_get_type ()) -#define GTK_GRAPH_DATA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_GRAPH_DATA, GtkGraphData)) -#define GTK_GRAPH_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_GRAPH_DATA, GtkGraphDataClass)) -#define GTK_IS_GRAPH_DATA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_GRAPH_DATA)) -#define GTK_IS_GRAPH_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_GRAPH_DATA)) -#define GTK_GRAPH_DATA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_GRAPH_DATA, GtkGraphDataClass)) +typedef struct _GraphData GraphData; -typedef struct _GtkGraphData GtkGraphData; -typedef struct _GtkGraphDataClass GtkGraphDataClass; -typedef struct _GtkGraphDataPrivate GtkGraphDataPrivate; +G_DECLARE_FINAL_TYPE (GraphData, graph_data, GRAPH, DATA, GObject) -struct _GtkGraphData -{ - GObject object; +GraphData *graph_data_new (guint n_values); - /*< private >*/ - GtkGraphDataPrivate *priv; -}; +guint graph_data_get_n_values (GraphData *data); +double graph_data_get_value (GraphData *data, + guint i); +double graph_data_get_minimum (GraphData *data); +double graph_data_get_maximum (GraphData *data); -struct _GtkGraphDataClass -{ - GObjectClass parent_class; - - /* Padding for future expansion */ - void (*_gtk_reserved1) (void); - void (*_gtk_reserved2) (void); - void (*_gtk_reserved3) (void); - void (*_gtk_reserved4) (void); -}; - - -GType gtk_graph_data_get_type (void) G_GNUC_CONST; - -GtkGraphData *gtk_graph_data_new (guint n_values); - -guint gtk_graph_data_get_n_values (GtkGraphData *data); -double gtk_graph_data_get_value (GtkGraphData *data, - guint i); -double gtk_graph_data_get_minimum (GtkGraphData *data); -double gtk_graph_data_get_maximum (GtkGraphData *data); - -void gtk_graph_data_prepend_value (GtkGraphData *data, - double value); +void graph_data_prepend_value (GraphData *data, + double value); G_END_DECLS -#endif /* __GTK_GRAPH_DATA_H__ */ +#endif /* __GRAPH_DATA_H__ */ diff --git a/gtk/inspector/graphrenderer.c b/gtk/inspector/graphrenderer.c new file mode 100644 index 0000000000..6ade21e5b2 --- /dev/null +++ b/gtk/inspector/graphrenderer.c @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2014 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" + +#include "graphrenderer.h" + +#include "graphdata.h" + +#include "gtksnapshot.h" +#include "gtkstylecontext.h" + +enum { + PROP_0, + PROP_DATA, + PROP_MINIMUM, + PROP_MAXIMUM +}; + +struct _GraphRenderer +{ + GtkWidget parent; + + GraphData *data; + double minimum; + double maximum; +}; + +G_DEFINE_TYPE (GraphRenderer, graph_renderer, GTK_TYPE_WIDGET) + +static void +graph_renderer_dispose (GObject *object) +{ + GraphRenderer *self = GRAPH_RENDERER (object); + + g_clear_object (&self->data); + + G_OBJECT_CLASS (graph_renderer_parent_class)->dispose (object); +} + +static void +graph_renderer_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + GraphRenderer *self = GRAPH_RENDERER (object); + + switch (param_id) + { + case PROP_DATA: + g_value_set_object (value, self->data); + break; + case PROP_MINIMUM: + g_value_set_double (value, self->minimum); + break; + case PROP_MAXIMUM: + g_value_set_double (value, self->maximum); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + } +} + +static void +graph_renderer_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + GraphRenderer *self = GRAPH_RENDERER (object); + + switch (param_id) + { + case PROP_DATA: + graph_renderer_set_data (self, g_value_get_object (value)); + break; + case PROP_MINIMUM: + if (self->minimum != g_value_get_double (value)) + { + self->minimum = g_value_get_double (value); + g_object_notify_by_pspec (object, pspec); + } + break; + case PROP_MAXIMUM: + if (self->maximum != g_value_get_double (value)) + { + self->maximum = g_value_get_double (value); + g_object_notify_by_pspec (object, pspec); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + } +} + +#define MIN_HEIGHT 24 +#define MIN_WIDTH (3 * MIN_HEIGHT) + +static void +graph_renderer_measure (GtkWidget *widget, + GtkOrientation orientation, + int for_size, + int *minimum, + int *natural, + int *minimum_baseline, + int *natural_baseline) +{ + if (orientation == GTK_ORIENTATION_HORIZONTAL) + *minimum = *natural = MIN_WIDTH; + else + *minimum = *natural = MIN_HEIGHT; +} + +static void +graph_renderer_snapshot (GtkWidget *widget, + GtkSnapshot *snapshot) +{ + GraphRenderer *self = GRAPH_RENDERER (widget); + GtkStyleContext *context; + double minimum, maximum, diff; + double x, y, width, height; + cairo_t *cr; + GdkRGBA color; + guint i, n; + +#define LINE_WIDTH 1.0 + + if (self->data == NULL) + return; + + if (self->minimum == -G_MAXDOUBLE) + minimum = graph_data_get_minimum (self->data); + else + minimum = self->minimum; + + if (self->maximum == G_MAXDOUBLE) + maximum = graph_data_get_maximum (self->data); + else + maximum = self->maximum; + + diff = maximum - minimum; + + context = gtk_widget_get_style_context (widget); + gtk_style_context_get_color (context, &color); + + cr = gtk_snapshot_append_cairo (snapshot, + &GRAPHENE_RECT_INIT ( + 0, 0, + gtk_widget_get_width (widget), + gtk_widget_get_height (widget) + )); + + cairo_set_line_width (cr, 1.0); + + x = LINE_WIDTH / 2.0; + y = LINE_WIDTH / 2.0; + width = gtk_widget_get_width (widget) - LINE_WIDTH; + height = gtk_widget_get_height (widget) - LINE_WIDTH; + + cairo_move_to (cr, x, y + height); + + if (diff > 0) + { + n = graph_data_get_n_values (self->data); + for (i = 0; i < n; i++) + { + double val = graph_data_get_value (self->data, i); + + val = (val - minimum) / diff; + val = y + height - val * height; + + cairo_line_to (cr, x + width * i / (n - 1), val); + } + } + + cairo_line_to (cr, x + width, y + height); + cairo_close_path (cr); + + gdk_cairo_set_source_rgba (cr, &color); + cairo_stroke_preserve (cr); + + color.alpha *= 0.2; + gdk_cairo_set_source_rgba (cr, &color); + cairo_fill (cr); + + cairo_destroy (cr); +} + +static void +graph_renderer_class_init (GraphRendererClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->dispose = graph_renderer_dispose; + object_class->get_property = graph_renderer_get_property; + object_class->set_property = graph_renderer_set_property; + + widget_class->measure = graph_renderer_measure; + widget_class->snapshot = graph_renderer_snapshot; + + g_object_class_install_property (object_class, + PROP_DATA, + g_param_spec_object ("data", NULL, NULL, + graph_data_get_type (), + G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); + + g_object_class_install_property (object_class, + PROP_MINIMUM, + g_param_spec_double ("minimum", NULL, NULL, + -G_MAXDOUBLE, G_MAXDOUBLE, -G_MAXDOUBLE, + G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); + + g_object_class_install_property (object_class, + PROP_MINIMUM, + g_param_spec_double ("maximum", NULL, NULL, + -G_MAXDOUBLE, G_MAXDOUBLE, G_MAXDOUBLE, + G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); +} + +static void +graph_renderer_init (GraphRenderer *self) +{ + self->minimum = -G_MAXDOUBLE; + self->maximum = G_MAXDOUBLE; +} + +GraphRenderer * +graph_renderer_new (void) +{ + return g_object_new (graph_renderer_get_type (), NULL); +} + +void +graph_renderer_set_data (GraphRenderer *self, + GraphData *data) +{ + if (g_set_object (&self->data, data)) + g_object_notify (G_OBJECT (self), "data"); + + gtk_widget_queue_draw (GTK_WIDGET (self)); +} diff --git a/gtk/inspector/graphrenderer.h b/gtk/inspector/graphrenderer.h new file mode 100644 index 0000000000..11f0a7ca9f --- /dev/null +++ b/gtk/inspector/graphrenderer.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __GRAPH_RENDERER_H__ +#define __GRAPH_RENDERER_H__ + +#include +#include "graphdata.h" + +G_BEGIN_DECLS + +typedef struct _GraphRenderer GraphRenderer; + +G_DECLARE_FINAL_TYPE (GraphRenderer, graph_renderer, GRAPH, RENDERER, GtkWidget); + +GraphRenderer *graph_renderer_new (void); + +void graph_renderer_set_data (GraphRenderer *self, + GraphData *data); + +G_END_DECLS + +#endif /* __GRAPH_RENDERER_H__ */ diff --git a/gtk/inspector/init.c b/gtk/inspector/init.c index 32f8cc1e1b..cc58d943db 100644 --- a/gtk/inspector/init.c +++ b/gtk/inspector/init.c @@ -26,7 +26,7 @@ #include "a11y.h" #include "actions.h" -#include "cellrenderergraph.h" +#include "graphrenderer.h" #include "clipboard.h" #include "controllers.h" #include "css-editor.h" @@ -66,8 +66,8 @@ gtk_inspector_init (void) g_type_ensure (G_TYPE_LIST_STORE); - g_type_ensure (GTK_TYPE_CELL_RENDERER_GRAPH); - g_type_ensure (GTK_TYPE_GRAPH_DATA); + g_type_ensure (graph_data_get_type ()); + g_type_ensure (graph_renderer_get_type ()); g_type_ensure (GTK_TYPE_INSPECTOR_A11Y); g_type_ensure (GTK_TYPE_INSPECTOR_ACTIONS); g_type_ensure (GTK_TYPE_INSPECTOR_CLIPBOARD); diff --git a/gtk/inspector/meson.build b/gtk/inspector/meson.build index f5bbe02cf9..3022031689 100644 --- a/gtk/inspector/meson.build +++ b/gtk/inspector/meson.build @@ -4,7 +4,6 @@ inspector_sources = files( 'action-holder.c', 'actions.c', 'baselineoverlay.c', - 'cellrenderergraph.c', 'clipboard.c', 'controllers.c', 'css-editor.c', @@ -14,6 +13,7 @@ inspector_sources = files( 'fpsoverlay.c', 'general.c', 'graphdata.c', + 'graphrenderer.c', 'gtktreemodelcssnode.c', 'gtkdataviewer.c', 'highlightoverlay.c', diff --git a/gtk/inspector/statistics.c b/gtk/inspector/statistics.c index b094fc2e93..97b671c308 100644 --- a/gtk/inspector/statistics.c +++ b/gtk/inspector/statistics.c @@ -20,21 +20,215 @@ #include "statistics.h" #include "graphdata.h" +#include "graphrenderer.h" -#include "gtkcelllayout.h" -#include "gtkcellrenderertext.h" #include "gtklabel.h" #include "gtksearchbar.h" #include "gtkstack.h" #include "gtktogglebutton.h" -#include "gtktreeselection.h" -#include "gtktreeview.h" -#include "gtkeventcontrollerkey.h" #include "gtkmain.h" -#include "gtkliststore.h" +#include "gtkcolumnview.h" +#include "gtkcolumnviewcolumn.h" +#include "gtksingleselection.h" +#include "gtksignallistitemfactory.h" +#include "gtklistitem.h" +#include "gtkstringsorter.h" +#include "gtknumericsorter.h" +#include "gtksortlistmodel.h" +#include "gtksearchentry.h" #include +/* {{{ TypeData object */ + +typedef struct _TypeData TypeData; + +G_DECLARE_FINAL_TYPE (TypeData, type_data, TYPE, DATA, GObject); + +struct _TypeData { + GObject parent; + + GType type; + GraphData *self; + GraphData *cumulative; +}; + +enum { + TYPE_DATA_PROP_NAME = 1, + TYPE_DATA_PROP_SELF1, + TYPE_DATA_PROP_CUMULATIVE1, + TYPE_DATA_PROP_SELF2, + TYPE_DATA_PROP_CUMULATIVE2, + TYPE_DATA_PROP_SELF, + TYPE_DATA_PROP_CUMULATIVE, +}; + +G_DEFINE_TYPE (TypeData, type_data, G_TYPE_OBJECT); + +static void +type_data_init (TypeData *self) +{ +} + +static void +type_data_finalize (GObject *object) +{ + TypeData *self = TYPE_DATA (object); + + g_object_unref (self->self); + g_object_unref (self->cumulative); + + G_OBJECT_CLASS (type_data_parent_class)->finalize (object); +} + +static void +type_data_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + TypeData *self = TYPE_DATA (object); + + switch (property_id) + { + case TYPE_DATA_PROP_NAME: + g_value_set_string (value, g_type_name (self->type)); + break; + + case TYPE_DATA_PROP_SELF1: + g_value_set_int (value, (int) graph_data_get_value (self->self, 1)); + break; + + case TYPE_DATA_PROP_CUMULATIVE1: + g_value_set_int (value, (int) graph_data_get_value (self->cumulative, 1)); + break; + + case TYPE_DATA_PROP_SELF2: + g_value_set_int (value, (int) graph_data_get_value (self->self, 0)); + break; + + case TYPE_DATA_PROP_CUMULATIVE2: + g_value_set_int (value, (int) graph_data_get_value (self->cumulative, 0)); + break; + + case TYPE_DATA_PROP_SELF: + g_value_set_object (value, self->self); + break; + + case TYPE_DATA_PROP_CUMULATIVE: + g_value_set_object (value, self->cumulative); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +type_data_class_init (TypeDataClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->finalize = type_data_finalize; + object_class->get_property = type_data_get_property; + + g_object_class_install_property (object_class, + TYPE_DATA_PROP_NAME, + g_param_spec_string ("name", NULL, NULL, + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, + TYPE_DATA_PROP_SELF1, + g_param_spec_int ("self1", NULL, NULL, + 0, G_MAXINT, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, + TYPE_DATA_PROP_CUMULATIVE1, + g_param_spec_int ("cumulative1", NULL, NULL, + 0, G_MAXINT, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, + TYPE_DATA_PROP_SELF2, + g_param_spec_int ("self2", NULL, NULL, + 0, G_MAXINT, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, + TYPE_DATA_PROP_CUMULATIVE2, + g_param_spec_int ("cumulative2", NULL, NULL, + 0, G_MAXINT, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, + TYPE_DATA_PROP_SELF, + g_param_spec_object ("self", NULL, NULL, + graph_data_get_type (), + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, + TYPE_DATA_PROP_CUMULATIVE, + g_param_spec_object ("cumulative", NULL, NULL, + graph_data_get_type (), + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} + +static TypeData * +type_data_new (GType type) +{ + TypeData *self; + + self = g_object_new (type_data_get_type (), NULL); + + self->type = type; + self->self = graph_data_new (60); + self->cumulative = graph_data_new (60); + + return self; +} + +static void +type_data_update (TypeData *data, + int self, + int cumulative) +{ + int value; + + g_object_freeze_notify (G_OBJECT (data)); + + value = graph_data_get_value (data->self, 0); + if (value != self) + g_object_notify (G_OBJECT (data), "self2"); + if (value != graph_data_get_value (data->self, 1)) + g_object_notify (G_OBJECT (data), "self1"); + + g_object_notify (G_OBJECT (data), "self"); + graph_data_prepend_value (data->self, self); + + value = graph_data_get_value (data->cumulative, 0); + if (value != cumulative) + g_object_notify (G_OBJECT (data), "cumulative2"); + if (value != graph_data_get_value (data->cumulative, 1)) + g_object_notify (G_OBJECT (data), "cumulative1"); + + g_object_notify (G_OBJECT (data), "cumulative"); + graph_data_prepend_value (data->cumulative, cumulative); + + g_object_thaw_notify (G_OBJECT (data)); +} + +/* }}} */ + enum { PROP_0, @@ -45,43 +239,16 @@ struct _GtkInspectorStatisticsPrivate { GtkWidget *stack; GtkWidget *excuse; - GtkTreeModel *model; - GtkTreeView *view; + GtkWidget *view; GtkWidget *button; - GHashTable *data; - GtkTreeViewColumn *column_self1; - GtkCellRenderer *renderer_self1; - GtkTreeViewColumn *column_cumulative1; - GtkCellRenderer *renderer_cumulative1; - GtkTreeViewColumn *column_self2; - GtkCellRenderer *renderer_self2; - GtkTreeViewColumn *column_cumulative2; - GtkCellRenderer *renderer_cumulative2; - GHashTable *counts; + GListStore *data; + GtkSingleSelection *selection; + GHashTable *types; guint update_source_id; GtkWidget *search_entry; GtkWidget *search_bar; }; -typedef struct { - GType type; - GtkTreeIter treeiter; - GtkGraphData *self; - GtkGraphData *cumulative; -} TypeData; - -enum -{ - COLUMN_TYPE, - COLUMN_TYPE_NAME, - COLUMN_SELF1, - COLUMN_CUMULATIVE1, - COLUMN_SELF2, - COLUMN_CUMULATIVE2, - COLUMN_SELF_DATA, - COLUMN_CUMULATIVE_DATA -}; - G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorStatistics, gtk_inspector_statistics, GTK_TYPE_BOX) static int @@ -92,6 +259,7 @@ add_type_count (GtkInspectorStatistics *sl, GType type) GType *children; guint n_children; int i; + guint idx; TypeData *data; cumulative = 0; @@ -100,35 +268,25 @@ add_type_count (GtkInspectorStatistics *sl, GType type) for (i = 0; i < n_children; i++) cumulative += add_type_count (sl, children[i]); - data = g_hash_table_lookup (sl->priv->counts, GSIZE_TO_POINTER (type)); - if (!data) + idx = GPOINTER_TO_UINT (g_hash_table_lookup (sl->priv->types, GSIZE_TO_POINTER (type))); + if (idx == 0) { - data = g_new0 (TypeData, 1); - data->type = type; - data->self = gtk_graph_data_new (60); - data->cumulative = gtk_graph_data_new (60); - gtk_list_store_append (GTK_LIST_STORE (sl->priv->model), &data->treeiter); - gtk_list_store_set (GTK_LIST_STORE (sl->priv->model), &data->treeiter, - COLUMN_TYPE, data->type, - COLUMN_TYPE_NAME, g_type_name (data->type), - COLUMN_SELF_DATA, data->self, - COLUMN_CUMULATIVE_DATA, data->cumulative, - -1); - g_hash_table_insert (sl->priv->counts, GSIZE_TO_POINTER (type), data); + g_list_store_append (sl->priv->data, type_data_new (type)); + idx = g_list_model_get_n_items (G_LIST_MODEL (sl->priv->data)); + g_hash_table_insert (sl->priv->types, GSIZE_TO_POINTER (type), GUINT_TO_POINTER (idx)); } + data = g_list_model_get_item (G_LIST_MODEL (sl->priv->data), idx - 1); + + g_assert (data->type == type); + self = g_type_get_instance_count (type); cumulative += self; - gtk_graph_data_prepend_value (data->self, self); - gtk_graph_data_prepend_value (data->cumulative, cumulative); + type_data_update (data, self, cumulative); + + g_object_unref (data); - gtk_list_store_set (GTK_LIST_STORE (sl->priv->model), &data->treeiter, - COLUMN_SELF1, (int) gtk_graph_data_get_value (data->self, 1), - COLUMN_CUMULATIVE1, (int) gtk_graph_data_get_value (data->cumulative, 1), - COLUMN_SELF2, (int) gtk_graph_data_get_value (data->self, 0), - COLUMN_CUMULATIVE2, (int) gtk_graph_data_get_value (data->cumulative, 0), - -1); return cumulative; } @@ -196,192 +354,449 @@ instance_counts_enabled (void) } static void -cell_data_data (GtkCellLayout *layout, - GtkCellRenderer *cell, - GtkTreeModel *model, - GtkTreeIter *iter, - gpointer data) +search_changed (GtkSearchEntry *entry, + GtkInspectorStatistics *sl) +{ + const char *text; + GListModel *model; + + text = gtk_editable_get_text (GTK_EDITABLE (entry)); + model = gtk_single_selection_get_model (sl->priv->selection); + + for (guint i = 0; i < g_list_model_get_n_items (model); i++) + { + TypeData *data = g_list_model_get_item (model, i); + char *string; + + g_object_unref (data); + + string = g_ascii_strdown (g_type_name (data->type), -1); + if (g_str_has_prefix (string, text)) + { + g_free (string); + gtk_single_selection_set_selected (sl->priv->selection, i); + return; + } + + g_free (string); + } + + gtk_single_selection_set_selected (sl->priv->selection, GTK_INVALID_LIST_POSITION); +} + +static void +root (GtkWidget *widget) +{ + GtkInspectorStatistics *sl = GTK_INSPECTOR_STATISTICS (widget); + GtkWidget *toplevel; + + GTK_WIDGET_CLASS (gtk_inspector_statistics_parent_class)->root (widget); + + toplevel = GTK_WIDGET (gtk_widget_get_root (widget)); + + gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (sl->priv->search_bar), toplevel); +} + +static void +unroot (GtkWidget *widget) +{ + GTK_WIDGET_CLASS (gtk_inspector_statistics_parent_class)->unroot (widget); +} + +static void +setup_label (GtkSignalListItemFactory *factory, + GtkListItem *list_item) +{ + GtkWidget *label; + + label = gtk_label_new (NULL); + gtk_label_set_xalign (GTK_LABEL (label), 0.); + gtk_list_item_set_child (list_item, label); +} + +static void +bind_name (GtkSignalListItemFactory *factory, + GtkListItem *list_item) +{ + GtkWidget *label; + TypeData *data; + + data = gtk_list_item_get_item (list_item); + label = gtk_list_item_get_child (list_item); + gtk_label_set_text (GTK_LABEL (label), g_type_name (data->type)); +} + +static void +set_self1 (TypeData *data, + GParamSpec *pspec, + GtkWidget *label) { - int column; int count; char *text; - column = GPOINTER_TO_INT (data); + g_object_get (data, "self1", &count, NULL); + text = g_strdup_printf ("%d", count); + gtk_label_set_text (GTK_LABEL (label), text); + g_free (text); +} + +static void +bind_self1 (GtkSignalListItemFactory *factory, + GtkListItem *list_item) +{ + GtkWidget *label; + TypeData *data; + + label = gtk_list_item_get_child (list_item); + data = gtk_list_item_get_item (list_item); + + set_self1 (data, NULL, label); + g_signal_connect (data, "notify::self1", G_CALLBACK (set_self1), label); +} + +static void +unbind_self1 (GtkSignalListItemFactory *factory, + GtkListItem *list_item) +{ + GtkWidget *label; + TypeData *data; + + label = gtk_list_item_get_child (list_item); + data = gtk_list_item_get_item (list_item); + + g_signal_handlers_disconnect_by_func (data, G_CALLBACK (set_self1), label); +} - gtk_tree_model_get (model, iter, column, &count, -1); +static void +set_cumulative1 (TypeData *data, + GParamSpec *pspec, + GtkWidget *label) +{ + int count; + char *text; + g_object_get (data, "cumulative1", &count, NULL); text = g_strdup_printf ("%d", count); - g_object_set (cell, "text", text, NULL); + gtk_label_set_text (GTK_LABEL (label), text); g_free (text); } static void -cell_data_delta (GtkCellLayout *layout, - GtkCellRenderer *cell, - GtkTreeModel *model, - GtkTreeIter *iter, - gpointer data) +bind_cumulative1 (GtkSignalListItemFactory *factory, + GtkListItem *list_item) +{ + GtkWidget *label; + TypeData *data; + + label = gtk_list_item_get_child (list_item); + data = gtk_list_item_get_item (list_item); + + set_cumulative1 (data, NULL, label); + g_signal_connect (data, "notify::cumulative1", G_CALLBACK (set_cumulative1), label); +} + +static void +unbind_cumulative1 (GtkSignalListItemFactory *factory, + GtkListItem *list_item) +{ + GtkWidget *label; + TypeData *data; + + label = gtk_list_item_get_child (list_item); + data = gtk_list_item_get_item (list_item); + + g_signal_handlers_disconnect_by_func (data, G_CALLBACK (set_cumulative1), label); +} + +static void +set_self2 (TypeData *data, + GParamSpec *pspec, + GtkWidget *label) { - int column; int count1; int count2; char *text; - column = GPOINTER_TO_INT (data); - - gtk_tree_model_get (model, iter, column - 2, &count1, column, &count2, -1); - + g_object_get (data, "self1", &count1, NULL); + g_object_get (data, "self2", &count2, NULL); if (count2 > count1) text = g_strdup_printf ("%d (↗ %d)", count2, count2 - count1); else if (count2 < count1) text = g_strdup_printf ("%d (↘ %d)", count2, count1 - count2); else text = g_strdup_printf ("%d", count2); - g_object_set (cell, "text", text, NULL); + gtk_label_set_text (GTK_LABEL (label), text); g_free (text); } static void -type_data_free (gpointer data) +bind_self2 (GtkSignalListItemFactory *factory, + GtkListItem *list_item) { - TypeData *type_data = data; + GtkWidget *label; + TypeData *data; - g_object_unref (type_data->self); - g_object_unref (type_data->cumulative); + label = gtk_list_item_get_child (list_item); + data = gtk_list_item_get_item (list_item); - g_free (type_data); + set_self2 (data, NULL, label); + g_signal_connect (data, "notify::self1", G_CALLBACK (set_self2), label); + g_signal_connect (data, "notify::self2", G_CALLBACK (set_self2), label); } -static gboolean -key_pressed (GtkEventController *controller, - guint keyval, - guint keycode, - GdkModifierType state, - GtkInspectorStatistics *sl) +static void +unbind_self2 (GtkSignalListItemFactory *factory, + GtkListItem *list_item) { - if (gtk_widget_get_mapped (GTK_WIDGET (sl))) - { - if (keyval == GDK_KEY_Return || - keyval == GDK_KEY_ISO_Enter || - keyval == GDK_KEY_KP_Enter) - { - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreePath *path; - - selection = gtk_tree_view_get_selection (sl->priv->view); - if (gtk_tree_selection_get_selected (selection, &model, &iter)) - { - path = gtk_tree_model_get_path (model, &iter); - gtk_tree_view_row_activated (sl->priv->view, path, NULL); - gtk_tree_path_free (path); - - return GDK_EVENT_STOP; - } - } - } + GtkWidget *label; + TypeData *data; + + label = gtk_list_item_get_child (list_item); + data = gtk_list_item_get_item (list_item); - return GDK_EVENT_PROPAGATE; + g_signal_handlers_disconnect_by_func (data, G_CALLBACK (set_self2), label); } -static gboolean -match_string (const char *string, - const char *text) +static void +set_cumulative2 (TypeData *data, + GParamSpec *pspec, + GtkWidget *label) +{ + int count1; + int count2; + char *text; + + g_object_get (data, "cumulative1", &count1, NULL); + g_object_get (data, "cumulative2", &count2, NULL); + if (count2 > count1) + text = g_strdup_printf ("%d (↗ %d)", count2, count2 - count1); + else if (count2 < count1) + text = g_strdup_printf ("%d (↘ %d)", count2, count1 - count2); + else + text = g_strdup_printf ("%d", count2); + gtk_label_set_text (GTK_LABEL (label), text); + g_free (text); +} + +static void +bind_cumulative2 (GtkSignalListItemFactory *factory, + GtkListItem *list_item) { - char *lower; - gboolean match = FALSE; + GtkWidget *label; + TypeData *data; - if (string) - { - lower = g_ascii_strdown (string, -1); - match = g_str_has_prefix (lower, text); - g_free (lower); - } + label = gtk_list_item_get_child (list_item); + data = gtk_list_item_get_item (list_item); - return match; + set_cumulative2 (data, NULL, label); + g_signal_connect (data, "notify::cumulative1", G_CALLBACK (set_cumulative2), label); + g_signal_connect (data, "notify::cumulative2", G_CALLBACK (set_cumulative2), label); } -static gboolean -match_row (GtkTreeModel *model, - int column, - const char *key, - GtkTreeIter *iter, - gpointer data) +static void +unbind_cumulative2 (GtkSignalListItemFactory *factory, + GtkListItem *list_item) { - char *type; - gboolean match; + GtkWidget *label; + TypeData *data; - gtk_tree_model_get (model, iter, column, &type, -1); + label = gtk_list_item_get_child (list_item); + data = gtk_list_item_get_item (list_item); - match = match_string (type, key); + g_signal_handlers_disconnect_by_func (data, G_CALLBACK (set_cumulative2), label); +} - g_free (type); +static void +setup_graph (GtkSignalListItemFactory *factory, + GtkListItem *list_item) +{ + gtk_list_item_set_child (list_item, GTK_WIDGET (graph_renderer_new ())); +} - return !match; +static void +set_graph_self (TypeData *data, + GParamSpec *pspec, + GtkWidget *graph) +{ + graph_renderer_set_data (GRAPH_RENDERER (graph), data->self); } static void -destroy_controller (GtkEventController *controller) +bind_graph_self (GtkSignalListItemFactory *factory, + GtkListItem *list_item) { - gtk_widget_remove_controller (gtk_event_controller_get_widget (controller), controller); + GtkWidget *graph; + TypeData *data; + + data = gtk_list_item_get_item (list_item); + graph = gtk_list_item_get_child (list_item); + + set_graph_self (data, NULL, graph); + g_signal_connect (data, "notify::self", G_CALLBACK (set_graph_self), graph); } static void -root (GtkWidget *widget) +unbind_graph_self (GtkSignalListItemFactory *factory, + GtkListItem *list_item) { - GtkInspectorStatistics *sl = GTK_INSPECTOR_STATISTICS (widget); - GtkEventController *controller; - GtkWidget *toplevel; + GtkWidget *graph; + TypeData *data; - GTK_WIDGET_CLASS (gtk_inspector_statistics_parent_class)->root (widget); + data = gtk_list_item_get_item (list_item); + graph = gtk_list_item_get_child (list_item); - toplevel = GTK_WIDGET (gtk_widget_get_root (widget)); + g_signal_handlers_disconnect_by_func (data, G_CALLBACK (set_graph_self), graph); +} - controller = gtk_event_controller_key_new (); - g_object_set_data_full (G_OBJECT (toplevel), "statistics-controller", controller, (GDestroyNotify)destroy_controller); - g_signal_connect (controller, "key-pressed", G_CALLBACK (key_pressed), widget); - gtk_widget_add_controller (toplevel, controller); +static void +set_graph_cumulative (TypeData *data, + GParamSpec *pspec, + GtkWidget *graph) +{ + graph_renderer_set_data (GRAPH_RENDERER (graph), data->cumulative); +} - gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (sl->priv->search_bar), toplevel); +static void +bind_graph_cumulative (GtkSignalListItemFactory *factory, + GtkListItem *list_item) +{ + GtkWidget *graph; + TypeData *data; + + data = gtk_list_item_get_item (list_item); + graph = gtk_list_item_get_child (list_item); + + set_graph_cumulative (data, NULL, graph); + g_signal_connect (data, "notify::cumulative", G_CALLBACK (set_graph_cumulative), graph); } static void -unroot (GtkWidget *widget) +unbind_graph_cumulative (GtkSignalListItemFactory *factory, + GtkListItem *list_item) { - GtkWidget *toplevel; + GtkWidget *graph; + TypeData *data; - toplevel = GTK_WIDGET (gtk_widget_get_root (widget)); - g_object_set_data (G_OBJECT (toplevel), "statistics-controller", NULL); + data = gtk_list_item_get_item (list_item); + graph = gtk_list_item_get_child (list_item); - GTK_WIDGET_CLASS (gtk_inspector_statistics_parent_class)->unroot (widget); + g_signal_handlers_disconnect_by_func (data, G_CALLBACK (set_graph_cumulative), graph); } static void gtk_inspector_statistics_init (GtkInspectorStatistics *sl) { + GtkColumnViewColumn *column; + GtkListItemFactory *factory; + GtkSorter *sorter; + GtkSortListModel *sort_model; + sl->priv = gtk_inspector_statistics_get_instance_private (sl); gtk_widget_init_template (GTK_WIDGET (sl)); - gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (sl->priv->column_self1), - sl->priv->renderer_self1, - cell_data_data, - GINT_TO_POINTER (COLUMN_SELF1), NULL); - gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (sl->priv->column_cumulative1), - sl->priv->renderer_cumulative1, - cell_data_data, - GINT_TO_POINTER (COLUMN_CUMULATIVE1), NULL); - gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (sl->priv->column_self2), - sl->priv->renderer_self2, - cell_data_delta, - GINT_TO_POINTER (COLUMN_SELF2), NULL); - gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (sl->priv->column_cumulative2), - sl->priv->renderer_cumulative2, - cell_data_delta, - GINT_TO_POINTER (COLUMN_CUMULATIVE2), NULL); - sl->priv->counts = g_hash_table_new_full (NULL, NULL, NULL, type_data_free); - - gtk_tree_view_set_search_entry (sl->priv->view, GTK_EDITABLE (sl->priv->search_entry)); - gtk_tree_view_set_search_equal_func (sl->priv->view, match_row, sl, NULL); + sl->priv->types = g_hash_table_new (NULL, NULL); + + sl->priv->data = g_list_store_new (type_data_get_type ()); + + sort_model = gtk_sort_list_model_new (G_LIST_MODEL (sl->priv->data), + g_object_ref (gtk_column_view_get_sorter (GTK_COLUMN_VIEW (sl->priv->view)))); + + sl->priv->selection = gtk_single_selection_new (G_LIST_MODEL (sort_model)); + gtk_single_selection_set_can_unselect (sl->priv->selection, TRUE); + + gtk_column_view_set_model (GTK_COLUMN_VIEW (sl->priv->view), GTK_SELECTION_MODEL (sl->priv->selection)); + + g_object_unref (sl->priv->selection); + + column = g_list_model_get_item (gtk_column_view_get_columns (GTK_COLUMN_VIEW (sl->priv->view)), 0); + + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_label), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_name), NULL); + + gtk_column_view_column_set_factory (column, factory); + sorter = GTK_SORTER (gtk_string_sorter_new (gtk_property_expression_new (type_data_get_type (), NULL, "name"))); + gtk_column_view_column_set_sorter (column, sorter); + g_object_unref (sorter); + g_object_unref (factory); + g_object_unref (column); + + column = g_list_model_get_item (gtk_column_view_get_columns (GTK_COLUMN_VIEW (sl->priv->view)), 1); + + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_label), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_self1), NULL); + g_signal_connect (factory, "unbind", G_CALLBACK (unbind_self1), NULL); + + gtk_column_view_column_set_factory (column, factory); + sorter = GTK_SORTER (gtk_numeric_sorter_new (gtk_property_expression_new (type_data_get_type (), NULL, "self1"))); + gtk_column_view_column_set_sorter (column, sorter); + g_object_unref (sorter); + g_object_unref (factory); + g_object_unref (column); + + column = g_list_model_get_item (gtk_column_view_get_columns (GTK_COLUMN_VIEW (sl->priv->view)), 2); + + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_label), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_cumulative1), NULL); + g_signal_connect (factory, "unbind", G_CALLBACK (unbind_cumulative1), NULL); + + gtk_column_view_column_set_factory (column, factory); + sorter = GTK_SORTER (gtk_numeric_sorter_new (gtk_property_expression_new (type_data_get_type (), NULL, "cumulative1"))); + gtk_column_view_column_set_sorter (column, sorter); + g_object_unref (sorter); + g_object_unref (factory); + g_object_unref (column); + + column = g_list_model_get_item (gtk_column_view_get_columns (GTK_COLUMN_VIEW (sl->priv->view)), 3); + + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_label), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_self2), NULL); + g_signal_connect (factory, "unbind", G_CALLBACK (unbind_self2), NULL); + + gtk_column_view_column_set_factory (column, factory); + sorter = GTK_SORTER (gtk_numeric_sorter_new (gtk_property_expression_new (type_data_get_type (), NULL, "self2"))); + gtk_column_view_column_set_sorter (column, sorter); + g_object_unref (sorter); + g_object_unref (factory); + g_object_unref (column); + + column = g_list_model_get_item (gtk_column_view_get_columns (GTK_COLUMN_VIEW (sl->priv->view)), 4); + + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_label), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_cumulative2), NULL); + g_signal_connect (factory, "unbind", G_CALLBACK (unbind_cumulative2), NULL); + + gtk_column_view_column_set_factory (column, factory); + sorter = GTK_SORTER (gtk_numeric_sorter_new (gtk_property_expression_new (type_data_get_type (), NULL, "cumulative2"))); + gtk_column_view_column_set_sorter (column, sorter); + g_object_unref (sorter); + g_object_unref (factory); + g_object_unref (column); + + column = g_list_model_get_item (gtk_column_view_get_columns (GTK_COLUMN_VIEW (sl->priv->view)), 5); + + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_graph), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_graph_self), NULL); + g_signal_connect (factory, "unbind", G_CALLBACK (unbind_graph_self), NULL); + + gtk_column_view_column_set_factory (column, factory); + g_object_unref (factory); + g_object_unref (column); + + column = g_list_model_get_item (gtk_column_view_get_columns (GTK_COLUMN_VIEW (sl->priv->view)), 6); + + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_graph), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_graph_cumulative), NULL); + g_signal_connect (factory, "unbind", G_CALLBACK (unbind_graph_cumulative), NULL); + + gtk_column_view_column_set_factory (column, factory); + g_object_unref (factory); + g_object_unref (column); } static void @@ -389,8 +804,7 @@ constructed (GObject *object) { GtkInspectorStatistics *sl = GTK_INSPECTOR_STATISTICS (object); - g_signal_connect (sl->priv->button, "toggled", - G_CALLBACK (toggle_record), sl); + g_signal_connect (sl->priv->button, "toggled", G_CALLBACK (toggle_record), sl); if (has_instance_counts ()) update_type_counts (sl); @@ -411,7 +825,7 @@ finalize (GObject *object) if (sl->priv->update_source_id) g_source_remove (sl->priv->update_source_id); - g_hash_table_unref (sl->priv->counts); + g_hash_table_unref (sl->priv->types); G_OBJECT_CLASS (gtk_inspector_statistics_parent_class)->finalize (object); } @@ -477,19 +891,10 @@ gtk_inspector_statistics_class_init (GtkInspectorStatisticsClass *klass) gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/statistics.ui"); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorStatistics, view); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorStatistics, stack); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorStatistics, model); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorStatistics, column_self1); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorStatistics, renderer_self1); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorStatistics, column_cumulative1); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorStatistics, renderer_cumulative1); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorStatistics, column_self2); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorStatistics, renderer_self2); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorStatistics, column_cumulative2); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorStatistics, renderer_cumulative2); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorStatistics, search_entry); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorStatistics, search_bar); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorStatistics, excuse); - + gtk_widget_class_bind_template_callback (widget_class, search_changed); } -// vim: set et sw=2 ts=2: +/* vim:set foldmethod=marker expandtab: */ diff --git a/gtk/inspector/statistics.ui b/gtk/inspector/statistics.ui index b081e3452d..5ce17f52fe 100644 --- a/gtk/inspector/statistics.ui +++ b/gtk/inspector/statistics.ui @@ -1,16 +1,4 @@ - - - - - - - - - - - -