aboutsummaryrefslogtreecommitdiff
path: root/src/statistics/gtk_statistics.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/statistics/gtk_statistics.c')
-rw-r--r--src/statistics/gtk_statistics.c87
1 files changed, 74 insertions, 13 deletions
diff --git a/src/statistics/gtk_statistics.c b/src/statistics/gtk_statistics.c
index b1d7fe84..c483794d 100644
--- a/src/statistics/gtk_statistics.c
+++ b/src/statistics/gtk_statistics.c
@@ -39,6 +39,9 @@
39 */ 39 */
40#define YTICKS 5 40#define YTICKS 5
41 41
42/**
43 * Additional distance between text and lines / borders in pixels.
44 */
42#define BORDER 10.0 45#define BORDER 10.0
43 46
44 47
@@ -66,6 +69,11 @@ struct ValueHistory
66{ 69{
67 70
68 /** 71 /**
72 * ID for value updates.
73 */
74 char *id;
75
76 /**
69 * Label for the subsystem. 77 * Label for the subsystem.
70 */ 78 */
71 char *label; 79 char *label;
@@ -172,9 +180,16 @@ gtk_statistics_new ()
172 180
173 181
174/** 182/**
183 * Add another data series to plot by the statistics widget.
184 *
185 * @param statistics widget to modify
186 * @param id identifier for the series
187 * @param label label to use
188 * @param color_name name of the color to use
175 */ 189 */
176void 190void
177gtk_statistics_add_line (GtkStatistics *statistics, 191gtk_statistics_add_line (GtkStatistics *statistics,
192 const char *id,
178 const char *label, 193 const char *label,
179 const char *color_name) 194 const char *color_name)
180{ 195{
@@ -188,6 +203,7 @@ gtk_statistics_add_line (GtkStatistics *statistics,
188 priv->values = g_realloc (priv->values, 203 priv->values = g_realloc (priv->values,
189 sizeof (struct ValueHistory*) * (1 + priv->num_values)); 204 sizeof (struct ValueHistory*) * (1 + priv->num_values));
190 priv->values[priv->num_values++] = vh = g_malloc (sizeof (struct ValueHistory)); 205 priv->values[priv->num_values++] = vh = g_malloc (sizeof (struct ValueHistory));
206 vh->id = strdup (id);
191 vh->label = strdup (label); 207 vh->label = strdup (label);
192 vh->red = c.red / 65535.0; 208 vh->red = c.red / 65535.0;
193 vh->green = c.green / 65535.0; 209 vh->green = c.green / 65535.0;
@@ -196,10 +212,16 @@ gtk_statistics_add_line (GtkStatistics *statistics,
196 212
197 213
198/** 214/**
215 * Add another value to a data series.
216 *
217 * @param statistics widget to update
218 * @param id identifier of the series
219 * @param x new x-value
220 * @param y new y-value
199 */ 221 */
200void 222void
201gtk_statistics_update_value (GtkStatistics *statistics, 223gtk_statistics_update_value (GtkStatistics *statistics,
202 const char *label, 224 const char *id,
203 uint64_t x, 225 uint64_t x,
204 uint64_t y) 226 uint64_t y)
205{ 227{
@@ -213,14 +235,15 @@ gtk_statistics_update_value (GtkStatistics *statistics,
213 for (i=0;i<priv->num_values;i++) 235 for (i=0;i<priv->num_values;i++)
214 { 236 {
215 vh = priv->values[i]; 237 vh = priv->values[i];
216 if (0 != strcmp (label, vh->label)) 238 if (0 != strcmp (id, vh->id))
217 continue; 239 continue;
240
218 if (++vh->last_history_offset == MAX_HISTORY) 241 if (++vh->last_history_offset == MAX_HISTORY)
219 vh->last_history_offset = 0; 242 vh->last_history_offset = 0;
220 if (vh->history_size < MAX_HISTORY) 243 if (vh->history_size < MAX_HISTORY)
221 vh->history_size++; 244 vh->history_size++;
222 vh->history[vh->last_history_offset].x = x; 245 vh->history[vh->last_history_offset].x = x;
223 vh->history[vh->last_history_offset].y = y; 246 vh->history[vh->last_history_offset].y = y;
224 widget = GTK_WIDGET (statistics); 247 widget = GTK_WIDGET (statistics);
225 if (gtk_widget_is_drawable (widget)) 248 if (gtk_widget_is_drawable (widget))
226 gtk_widget_queue_draw (widget); 249 gtk_widget_queue_draw (widget);
@@ -228,11 +251,19 @@ gtk_statistics_update_value (GtkStatistics *statistics,
228} 251}
229 252
230 253
254/**
255 * Convert a number to a nice label for the axis.
256 *
257 * @param num number to convert
258 * @param label where to store the string (must be big enough!)
259 */
231static void 260static void
232num_to_label (unsigned long long num, 261num_to_label (unsigned long long num,
233 char *label) 262 char *label)
234{ 263{
235 if (num > 1000LL * 1000 * 1000 * 3) 264 if (num > 1000LL * 1000 * 1000 * 1000 * 3)
265 sprintf (label, "%llu t", num / 1000LL / 1000LL / 1000LL / 1000LL);
266 else if (num > 1000LL * 1000 * 1000 * 3)
236 sprintf (label, "%llu g", num / 1000LL / 1000LL / 1000LL); 267 sprintf (label, "%llu g", num / 1000LL / 1000LL / 1000LL);
237 else if (num > 1000LL * 1000 * 3) 268 else if (num > 1000LL * 1000 * 3)
238 sprintf (label, "%llu m", num / 1000LL / 1000LL); 269 sprintf (label, "%llu m", num / 1000LL / 1000LL);
@@ -243,6 +274,12 @@ num_to_label (unsigned long long num,
243} 274}
244 275
245 276
277/**
278 * Draw the statistics widget.
279 *
280 * @param widget widget to draw
281 * @param cr drawing context
282 */
246static gboolean 283static gboolean
247gtk_statistics_draw (GtkWidget *widget, 284gtk_statistics_draw (GtkWidget *widget,
248 cairo_t *cr) 285 cairo_t *cr)
@@ -264,6 +301,7 @@ gtk_statistics_draw (GtkWidget *widget,
264 cairo_text_extents_t tey_max; 301 cairo_text_extents_t tey_max;
265 double rx; 302 double rx;
266 double ry; 303 double ry;
304 unsigned int h;
267 305
268 /* collect basic data */ 306 /* collect basic data */
269 xmin = UINT64_MAX; 307 xmin = UINT64_MAX;
@@ -292,7 +330,7 @@ gtk_statistics_draw (GtkWidget *widget,
292 cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); 330 cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
293 cairo_paint(cr); 331 cairo_paint(cr);
294 332
295 if (0 == priv->num_values) 333 if ( (0 == priv->num_values) || (ymax == 0) )
296 return FALSE; /* done */ 334 return FALSE; /* done */
297 /* select font */ 335 /* select font */
298 cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); 336 cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
@@ -379,10 +417,26 @@ gtk_statistics_draw (GtkWidget *widget,
379 417
380 /* finally, plot lines */ 418 /* finally, plot lines */
381 cairo_set_line_width (cr, 2.0); 419 cairo_set_line_width (cr, 2.0);
420
421 cairo_set_font_size (cr,
422 GNUNET_MIN (20, (height - 3.0 * BORDER - tex_max.height - tey_max.height / 2) / (priv->num_values + 1)));
423
424 h = 2.0 * BORDER + tey_max.height / 2;
425
382 for (i=0;i<priv->num_values;i++) 426 for (i=0;i<priv->num_values;i++)
383 { 427 {
384 vh = priv->values[i]; 428 vh = priv->values[i];
385 cairo_set_source_rgb(cr, vh->red, vh->green, vh->blue); 429 cairo_set_source_rgb(cr, vh->red, vh->green, vh->blue);
430 cairo_text_extents (cr, vh->label, &te);
431 h += te.height / 2;
432 cairo_move_to (cr,
433 3.0 * BORDER + tey_max.width,
434 h);
435 h += te.height / 2 + 1.0;
436 cairo_show_text (cr, vh->label);
437 if (xmax == xmin)
438 continue;
439
386 for (j=0;j<vh->history_size;j++) 440 for (j=0;j<vh->history_size;j++)
387 { 441 {
388 hv = &vh->history[(vh->last_history_offset - j + MAX_HISTORY) % MAX_HISTORY]; 442 hv = &vh->history[(vh->last_history_offset - j + MAX_HISTORY) % MAX_HISTORY];
@@ -391,14 +445,15 @@ gtk_statistics_draw (GtkWidget *widget,
391 445
392 rx = tey_max.width + BORDER * 2.0 + (rx * (width - BORDER * 3.0 - tey_max.width - tex_max.width / 2.0)); 446 rx = tey_max.width + BORDER * 2.0 + (rx * (width - BORDER * 3.0 - tey_max.width - tex_max.width / 2.0));
393 ry = BORDER + tex_max.height / 2.0 + (1.0 - ry) * (height - BORDER * 2.0 - tey_max.height - tex_max.height); 447 ry = BORDER + tex_max.height / 2.0 + (1.0 - ry) * (height - BORDER * 2.0 - tey_max.height - tex_max.height);
394 if (j == 0) 448
395 { 449 /* if y-values are small, offset y-values a bit to allow overlapping curves to still show up */
396 cairo_move_to (cr, rx, ry); 450 if (ymax < height / (priv->num_values * 4))
397 } 451 ry += priv->num_values * 2 - (4 * i);
398 else 452 if (j == 0)
399 { 453 cairo_move_to (cr,
400 cairo_line_to (cr, rx, ry); 454 width - BORDER - tex_max.width / 2.0,
401 } 455 ry);
456 cairo_line_to (cr, rx, ry);
402 } 457 }
403 cairo_stroke (cr); 458 cairo_stroke (cr);
404 } 459 }
@@ -406,6 +461,11 @@ gtk_statistics_draw (GtkWidget *widget,
406} 461}
407 462
408 463
464/**
465 * Free memory used by statistics object.
466 *
467 * @param object object to release
468 */
409static void 469static void
410gtk_statistics_finalize (GObject *object) 470gtk_statistics_finalize (GObject *object)
411{ 471{
@@ -416,6 +476,7 @@ gtk_statistics_finalize (GObject *object)
416 for (i=0;i<priv->num_values;i++) 476 for (i=0;i<priv->num_values;i++)
417 { 477 {
418 g_free (priv->values[i]->label); 478 g_free (priv->values[i]->label);
479 g_free (priv->values[i]->id);
419 g_free (priv->values[i]); 480 g_free (priv->values[i]);
420 } 481 }
421 g_free (priv->values); 482 g_free (priv->values);