diff options
Diffstat (limited to 'loadgraph.c')
-rw-r--r-- | loadgraph.c | 149 |
1 files changed, 119 insertions, 30 deletions
diff --git a/loadgraph.c b/loadgraph.c index 53fb54f7..5f61fca3 100644 --- a/loadgraph.c +++ b/loadgraph.c @@ -33,6 +33,9 @@ LoadGraph *load_graph_new(gint size) lg = g_new0(LoadGraph, 1); + size++; + + lg->suffix = g_strdup(""); lg->area = gtk_drawing_area_new(); lg->size = size; lg->data = g_new0(gint, size); @@ -42,12 +45,28 @@ LoadGraph *load_graph_new(gint size) lg->width = size * 4; lg->height = size * 2; + lg->max_value = 1; + lg->remax_count = 0; + + lg->layout = pango_layout_new(gtk_widget_get_pango_context (lg->area)); + gtk_widget_set_size_request(lg->area, lg->width, lg->height); gtk_widget_show(lg->area); return lg; } +void load_graph_set_data_suffix(LoadGraph *lg, gchar *suffix) +{ + g_free(lg->suffix); + lg->suffix = g_strdup(suffix); +} + +gchar *load_graph_get_data_suffix(LoadGraph *lg) +{ + return lg->suffix; +} + GtkWidget *load_graph_get_framed(LoadGraph *lg) { GtkWidget *align, *frame; @@ -73,6 +92,9 @@ void load_graph_clear(LoadGraph *lg) lg->data[i] = 0; lg->scale = 1.0; + lg->max_value = 1; + lg->remax_count = 0; + _draw(lg); } @@ -80,6 +102,8 @@ void load_graph_set_color(LoadGraph *lg, LoadGraphColor color) { lg->color = color; gdk_rgb_gc_set_foreground(lg->trace, lg->color); + gdk_rgb_gc_set_foreground(lg->fill, lg->color - 0x303030); + gdk_rgb_gc_set_foreground(lg->grid, lg->color - 0x404040); } void load_graph_destroy(LoadGraph *lg) @@ -89,6 +113,8 @@ void load_graph_destroy(LoadGraph *lg) gdk_pixmap_unref(lg->buf); g_object_unref(lg->trace); g_object_unref(lg->grid); + g_object_unref(lg->fill); + g_object_unref(lg->layout); g_free(lg); } @@ -116,6 +142,7 @@ void load_graph_configure_expose(LoadGraph *lg) /* create the graphic contexts */ lg->grid = gdk_gc_new(GDK_DRAWABLE(lg->buf)); lg->trace = gdk_gc_new(GDK_DRAWABLE(lg->buf)); + lg->fill = gdk_gc_new(GDK_DRAWABLE(lg->buf)); /* the default color is green */ load_graph_set_color(lg, LG_COLOR_GREEN); @@ -125,19 +152,49 @@ void load_graph_configure_expose(LoadGraph *lg) 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_NOT_LAST, GDK_JOIN_ROUND); +#if 0 /* old-style grid */ gdk_rgb_gc_set_foreground(lg->grid, 0x707070); +#endif gdk_gc_set_line_attributes(lg->trace, - 2, GDK_LINE_SOLID, - GDK_CAP_NOT_LAST, + 1, GDK_LINE_SOLID, + GDK_CAP_PROJECTING, GDK_JOIN_ROUND); +#if 0 /* old-style fill */ + gdk_gc_set_line_attributes(lg->fill, + 1, GDK_LINE_SOLID, + GDK_CAP_BUTT, + GDK_JOIN_BEVEL); +#endif + /* configures the expose event */ g_signal_connect(G_OBJECT(lg->area), "expose-event", (GCallback) _expose, lg); } static void +_draw_label_and_line(LoadGraph *lg, gint position, gint value) +{ + gchar *tmp; + + /* draw lines */ + if (position > 0) + gdk_draw_line(GDK_DRAWABLE(lg->buf), lg->grid, 0, position, lg->width, position); + else + position = -1 * position; + + /* draw label */ + tmp = g_strdup_printf("<span size=\"x-small\">%d%s</span>", value, lg->suffix); + + pango_layout_set_markup(lg->layout, tmp, -1); + pango_layout_set_width(lg->layout, lg->area->allocation.width * PANGO_SCALE); + gdk_draw_layout(GDK_DRAWABLE(lg->buf), lg->trace, 2, position, lg->layout); + + g_free(tmp); +} + +static void _draw(LoadGraph *lg) { GdkDrawable *draw = GDK_DRAWABLE(lg->buf); @@ -147,45 +204,58 @@ _draw(LoadGraph *lg) gdk_draw_rectangle(draw, lg->area->style->black_gc, TRUE, 0, 0, lg->width, lg->height); - /* horizontal bars; 25%, 50% and 75% */ - d = lg->height / 4; - gdk_draw_line(draw, lg->grid, 0, d, lg->width, d); - d = lg->height / 2; - gdk_draw_line(draw, lg->grid, 0, d, lg->width, d); - d = 3 * (lg->height / 4); - gdk_draw_line(draw, lg->grid, 0, d, lg->width, d); + + /* the graph */ + GdkPoint *points = g_new0(GdkPoint, lg->size + 1); + + for (i = 0; i < lg->size; i++) { + points[i].x = i * 4; + points[i].y = lg->height - lg->data[i] * lg->scale; + } + + points[0].x = points[1].x = 0; + points[0].y = points[i].y = lg->height; + points[i].x = points[i-1].x = lg->width; + + gdk_draw_polygon(draw, lg->fill, TRUE, points, lg->size + 1); + gdk_draw_polygon(draw, lg->trace, FALSE, points, lg->size + 1); + + g_free(points); /* vertical bars */ for (i = lg->width, d = 0; i > 1; i--, d++) if ((d % 45) == 0 && d) gdk_draw_line(draw, lg->grid, i, 0, i, lg->height); - /* the graph */ + /* horizontal bars and labels; 25%, 50% and 75% */ + _draw_label_and_line(lg, -1, lg->max_value); + _draw_label_and_line(lg, lg->height / 4, 3 * (lg->max_value / 4)); + _draw_label_and_line(lg, lg->height / 2, lg->max_value / 2); + _draw_label_and_line(lg, 3 * (lg->height / 4), lg->max_value / 4); + +#if 0 /* old-style drawing */ for (i = 0; i < lg->size; i++) { gint this = lg->height - lg->data[i] * lg->scale; gint next = lg->height - lg->data[i+1] * lg->scale; + gint i4 = i * 4; - gdk_draw_line(draw, lg->trace, i * 4, this, i * 4 + 2, - (this + next) / 2); - gdk_draw_line(draw, lg->trace, i * 4 + 2, (this + next) / 2, - i * 4 + 4, next); + gdk_draw_line(draw, lg->fill, i4, this, i4, lg->height); + gdk_draw_line(draw, lg->fill, i4 + 2, this, i4 + 2, lg->height); } - - gtk_widget_queue_draw(lg->area); -} -static inline int -_max(LoadGraph *lg) -{ - gint i; - gint max = 1.0; + for (i = 0; i < lg->size; i++) { + gint this = lg->height - lg->data[i] * lg->scale; + gint next = lg->height - lg->data[i+1] * lg->scale; + gint i4 = i * 4; - for (i = 0; i < lg->size; i++) { - if (lg->data[i] > max) - max = lg->data[i]; + gdk_draw_line(draw, lg->trace, i4, this, i4 + 2, + (this + next) / 2); + gdk_draw_line(draw, lg->trace, i4 + 2, (this + next) / 2, + i4 + 4, next); } - - return max; +#endif + + gtk_widget_queue_draw(lg->area); } void @@ -196,8 +266,6 @@ load_graph_update(LoadGraph *lg, gint value) if (value < 0) return; - lg->scale = (gfloat)lg->height / (gfloat)_max(lg); - /* shift-right our data */ for (i = 0; i < lg->size; i++) { lg->data[i] = lg->data[i+1]; @@ -206,6 +274,27 @@ load_graph_update(LoadGraph *lg, gint value) /* insert the updated value */ lg->data[i] = value; + /* calculates the maximum value */ + if (lg->remax_count++ > 20) { + /* only finds the maximum amongst the data every 20 times */ + lg->remax_count = 0; + + gint max = lg->data[0]; + for (i = 1; i < lg->size; i++) { + if (lg->data[i] > max) + max = lg->data[i]; + } + + lg->max_value = max; + } else { + /* otherwise, select the maximum between the current maximum + and the supplied value */ + lg->max_value = MAX(value, lg->max_value); + } + + /* recalculates the scale; always use 90% of it */ + lg->scale = 0.90 * ((gfloat)lg->height / (gfloat)lg->max_value); + /* redraw */ _draw(lg); } @@ -242,7 +331,7 @@ int main(int argc, char **argv) window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_widget_show(window); - lg = load_graph_new(200); + lg = load_graph_new(50); gtk_container_add(GTK_CONTAINER(window), load_graph_get_framed(lg)); gtk_container_set_border_width(GTK_CONTAINER(window), 20); load_graph_configure_expose(lg); |