2 * h/t https://ptomato.name/advanced-gtk-techniques/html/custom-container.html
3 * for examples of how to make GTK widgets
10 #define BV_CHART_PRIVATE(obj) \
11 (G_TYPE_INSTANCE_GET_PRIVATE((obj), BV_CHART_TYPE, BVChartPrivate))
13 typedef struct _BVChartPrivate BVChartPrivate
;
15 struct _BVChartPrivate
{
17 float minx
, miny
, maxx
, maxy
;
24 G_DEFINE_TYPE_WITH_CODE(BVChart
, bv_chart
, GTK_TYPE_DRAWING_AREA
,
25 G_ADD_PRIVATE(BVChart
))
27 typedef void (*cairo_draw_func
)(cairo_t
*cr
, double x
, double y
);
29 static gboolean
bv_chart_draw(GtkWidget
*widget
, cairo_t
*cr
) {
30 BVChart
*chart
= BV_CHART(widget
);
31 BVChartPrivate
*priv
= bv_chart_get_instance_private(chart
);
33 cairo_set_source_rgb(cr
, 1.0, 1.0, 1.0);
36 if (priv
->points
->len
< 2)
39 GtkAllocation allocation
;
40 gtk_widget_get_allocation(widget
, &allocation
);
43 float xscale
= (allocation
.width
- 2 * margin
) / (priv
->maxx
- priv
->minx
);
44 float yscale
= (allocation
.height
- 2 * margin
) / (priv
->miny
- priv
->maxy
);
45 cairo_set_source_rgb(cr
, 0.0, 0.0, 1.0);
46 float gap_threshold
= 3.0;
48 for (guint i
= 0; i
< priv
->points
->len
; i
++) {
49 struct BVChartPoint
*p
=
50 &g_array_index(priv
->points
, struct BVChartPoint
, i
);
51 gboolean is_gap
= p
->x
- prevx
> gap_threshold
;
52 cairo_draw_func f
= is_gap
? cairo_move_to
: cairo_line_to
;
53 float screen_x
= xscale
* (p
->x
- priv
->minx
) + margin
;
54 float screen_y
= yscale
* (p
->y
- priv
->maxy
) + margin
;
55 f(cr
, screen_x
, screen_y
);
63 static void bv_chart_class_init(BVChartClass
*klass
) {
64 GtkWidgetClass
*widget_class
= GTK_WIDGET_CLASS(klass
);
65 widget_class
->draw
= bv_chart_draw
;
68 static void bv_chart_init(BVChart
*chart
) {
69 gtk_widget_set_has_window(GTK_WIDGET(chart
), FALSE
);
70 BVChartPrivate
*priv
= bv_chart_get_instance_private(chart
);
71 gboolean zero_terminated
= FALSE
;
72 gboolean clear_
= FALSE
;
74 g_array_new(zero_terminated
, clear_
, sizeof(struct BVChartPoint
));
81 GtkWidget
*bv_chart_new() {
82 return GTK_WIDGET(g_object_new(bv_chart_get_type(), NULL
));
85 void bv_chart_add_point(BVChart
*chart
, float x
, float y
) {
86 BVChartPrivate
*priv
= bv_chart_get_instance_private(chart
);
95 struct BVChartPoint p
= {.x
= x
, .y
= y
};
96 g_array_append_val(priv
->points
, p
);