diff options
-rw-r--r-- | src/callgraph.c | 149 |
1 files changed, 147 insertions, 2 deletions
diff --git a/src/callgraph.c b/src/callgraph.c index 97d1970..bfa1e02 100644 --- a/src/callgraph.c +++ b/src/callgraph.c @@ -547,6 +547,125 @@ cell_renderer_distribution_init (CellRendererDistribution *self) } +typedef struct _CellRendererFraction { + GtkCellRenderer renderer; + + gdouble fraction; +} CellRendererFraction; +typedef struct _CellRendererFractionClass { + GtkCellRendererClass parent_class; +} CellRendererFractionClass; + +static GType +cell_renderer_fraction_get_type (void); + +G_DEFINE_TYPE (CellRendererFraction, cell_renderer_fraction, GTK_TYPE_CELL_RENDERER) + +static void +cell_renderer_fraction_get_size (GtkCellRenderer *cell, + GtkWidget *widget, + GdkRectangle *rectangle, + gint *x_offset, + gint *y_offset, + gint *width, + gint *height) +{ + if (x_offset) + *x_offset = 0; + if (y_offset) + *y_offset = 0; + if (width) + *width = 16; + if (height) + *height = 16; +} + +static void +cell_renderer_fraction_render (GtkCellRenderer *cell, + GdkDrawable *window, + GtkWidget *widget, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GdkRectangle *expose_area, + GtkCellRendererState flags) +{ + CellRendererFraction *self = (CellRendererFraction *) cell; + cairo_t *cr = gdk_cairo_create (window); + + cairo_translate (cr, cell_area->x, cell_area->y); + + cairo_new_path (cr); + cairo_arc (cr, 8, 8, 6, 0, 2 * G_PI); + cairo_set_line_width (cr, 1); + cairo_stroke (cr); + + cairo_move_to (cr, 8, 8); + cairo_arc (cr, 8, 8, 6, -G_PI/2, self->fraction * 2 * G_PI - G_PI/2); + cairo_fill (cr); + + cairo_destroy (cr); +} + +enum { + CRF_PROP_0 = 0, + CRF_PROP_FRACTION +}; + +static void +cell_renderer_fraction_set_property (GObject *obj, guint id, const GValue *v, GParamSpec *spec) +{ + CellRendererFraction *self = (CellRendererFraction *) obj; + switch (id) { + case CRF_PROP_FRACTION: + self->fraction = g_value_get_double (v); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, spec); + break; + } +} + +static void +cell_renderer_fraction_class_init (CellRendererFractionClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + GtkCellRendererClass *cell_class = (GtkCellRendererClass *) klass; + + cell_class->get_size = cell_renderer_fraction_get_size; + cell_class->render = cell_renderer_fraction_render; + + object_class->set_property = cell_renderer_fraction_set_property; + + g_object_class_install_property (object_class, + CRF_PROP_FRACTION, + g_param_spec_double ("fraction", + _("fraction"), + _("Fraction"), + 0, 1., .5, + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB | + G_PARAM_STATIC_NAME | + G_PARAM_WRITABLE)); +} + +static void +cell_renderer_fraction_init (CellRendererFraction *self) +{ +} + + +static void +render_frame_fraction (GtkCellLayout *layout, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer data) +{ + CallGraphFrame *frame = iter->user_data; + g_object_set (G_OBJECT (cell), + "fraction", frame->filter_parent ? frame->allocs / (gdouble) frame->filter_parent->allocs : 1., + NULL); +} static void render_size_distribution (GtkCellLayout *layout, GtkCellRenderer *cell, @@ -608,20 +727,43 @@ custom_header (CallGraph *self, GtkTreeViewColumn *column) return hbox; } + +static void +autoexpand_children (CallGraph *self, GtkTreeIter *iter, GtkTreePath *path) +{ + CallGraphFrame *frame = iter->user_data; + if (frame->n_filter == 1) { + GtkTreeIter child; + + child.stamp = self->model->stamp; + child.user_data = frame->filter[0]; + path = gtk_tree_model_get_path ((GtkTreeModel *) self->model, &child); + gtk_tree_view_expand_to_path (&self->tv, path); + gtk_tree_path_free (path); + } +} + static void call_graph_init (CallGraph *self) { GtkTreeViewColumn *column; GtkCellRenderer *renderer; + column = gtk_tree_view_column_new (); + renderer = g_object_new (cell_renderer_fraction_get_type (), NULL); + gtk_tree_view_column_pack_start (column, renderer, FALSE); + gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (column), renderer, + render_frame_fraction, NULL, NULL); + renderer = gtk_cell_renderer_text_new (); g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, "ellipsize-set", TRUE, "width-chars", 50, NULL); - column = gtk_tree_view_column_new_with_attributes ("Frame", - renderer, "text", CG_FRAME, NULL); + gtk_tree_view_column_pack_start (column, renderer, TRUE); + gtk_tree_view_column_add_attribute (column, renderer, "text", CG_FRAME); + gtk_tree_view_column_set_widget (column, custom_header (self, column)); gtk_tree_view_column_set_expand (column, TRUE); gtk_tree_view_append_column (&self->tv, column); @@ -663,6 +805,9 @@ call_graph_init (CallGraph *self) gtk_tree_view_set_enable_tree_lines (&self->tv, TRUE); gtk_tree_view_set_rules_hint (&self->tv, TRUE); + g_signal_connect (&self->tv, "row-expanded", + G_CALLBACK (autoexpand_children), NULL); + gtk_widget_set_has_tooltip (GTK_WIDGET (self), TRUE); } |