/** * uber_line_graph_get_next_data: * @graph: A #UberGraph. * * XXX * * Returns: None. * Side effects: None. */ static gboolean uber_line_graph_get_next_data (UberGraph *graph) /* IN */ { UberLineGraphPrivate *priv; LineInfo *line; gdouble val; gboolean ret = FALSE; gint i; g_return_val_if_fail(UBER_IS_LINE_GRAPH(graph), FALSE); priv = UBER_LINE_GRAPH(graph)->priv; /* * Retrieve the next data point. */ if (priv->func) { for (i = 0; i < priv->lines->len; i++) { val = 0.; line = &g_array_index(priv->lines, LineInfo, i); if (!(ret = priv->func(UBER_LINE_GRAPH(graph), i + 1, &val, priv->func_data))) { val = -INFINITY; } g_ring_append_val(line->raw_data, val); /* * TODO: Scale value. */ g_ring_append_val(line->scaled_data, val); } } return ret; }
/** * uber_line_graph_get_next_data: * @graph: A #UberGraph. * * XXX * * Returns: None. * Side effects: None. */ static gboolean uber_line_graph_get_next_data (UberGraph *graph) /* IN */ { UberLineGraphPrivate *priv; gboolean scale_changed = FALSE; gboolean ret = FALSE; LineInfo *line; gdouble val; gint i; g_return_val_if_fail(UBER_IS_LINE_GRAPH(graph), FALSE); priv = UBER_LINE_GRAPH(graph)->priv; /* * Retrieve the next data point. */ if (priv->func) { for (i = 0; i < priv->lines->len; i++) { val = 0.; line = &g_array_index(priv->lines, LineInfo, i); if (!(ret = priv->func(UBER_LINE_GRAPH(graph), i + 1, &val, priv->func_data))) { val = -INFINITY; } g_ring_append_val(line->raw_data, val); if (priv->autoscale) { if (val < priv->range.begin) { priv->range.begin = val - (val * SCALE_FACTOR); priv->range.range = priv->range.end - priv->range.begin; scale_changed = TRUE; } else if (val > priv->range.end) { priv->range.end = val + (val * SCALE_FACTOR); priv->range.range = priv->range.end - priv->range.begin; scale_changed = TRUE; } } } } if (scale_changed) { uber_graph_scale_changed(graph); } return ret; }
/** * uber_line_graph_set_data_func: * @graph: A #UberLineGraph. * * XXX * * Returns: None. * Side effects: None. */ void uber_line_graph_set_data_func (UberLineGraph *graph, /* IN */ UberLineGraphFunc func, /* IN */ gpointer user_data, /* IN */ GDestroyNotify notify) /* IN */ { UberLineGraphPrivate *priv; g_return_if_fail(UBER_IS_LINE_GRAPH(graph)); priv = graph->priv; /* * Free existing data func if neccessary. */ if (priv->func_notify) { priv->func_notify(priv->func_data); } /* * Store data func. */ priv->func = func; priv->func_data = user_data; priv->func_notify = notify; }
/** * uber_line_graph_render_fast: * @graph: A #UberGraph. * * XXX * * Returns: None. * Side effects: None. */ static void uber_line_graph_render_fast (UberGraph *graph, /* IN */ cairo_t *cr, /* IN */ GdkRectangle *rect, /* IN */ guint epoch, /* IN */ gfloat each) /* IN */ { UberLineGraphPrivate *priv; UberRange pixel_range; LineInfo *line; gdouble last_y; gdouble y; gint i; g_return_if_fail(UBER_IS_LINE_GRAPH(graph)); g_return_if_fail(cr != NULL); g_return_if_fail(rect != NULL); priv = UBER_LINE_GRAPH(graph)->priv; pixel_range.begin = rect->y + 1; pixel_range.end = rect->y + rect->height; pixel_range.range = pixel_range.end - pixel_range.begin; /* * Render most recent data point for each line. */ for (i = 0; i < priv->lines->len; i++) { line = &g_array_index(priv->lines, LineInfo, i); uber_line_graph_stylize_line(UBER_LINE_GRAPH(graph), line, cr); /* * Calculate positions. */ y = g_ring_get_index(line->raw_data, gdouble, 0); last_y = g_ring_get_index(line->raw_data, gdouble, 1); /* * Don't try to draw before we have real values. */ if ((isnan(y) || isinf(y)) || (isnan(last_y) || isinf(last_y))) { continue; } /* * Translate to coordinate scale. */ if (!priv->scale(&priv->range, &pixel_range, &y, priv->scale_data) || !priv->scale(&priv->range, &pixel_range, &last_y, priv->scale_data)) { continue; } /* * Translate position from bottom right corner. */ y = (gint)(RECT_BOTTOM(*rect) - y) - .5; last_y = (gint)(RECT_BOTTOM(*rect) - last_y) - .5; /* * Convert relative position to fixed from bottom pixel. */ cairo_new_path(cr); cairo_move_to(cr, epoch, y); cairo_curve_to(cr, epoch - (each / 2.), y, epoch - (each / 2.), last_y, epoch - each, last_y); cairo_stroke(cr); } }
/** * uber_line_graph_render: * @graph: A #UberGraph. * @cr: A #cairo_t context. * @area: Full area to render contents within. * @line: The line to render. * * Render a particular line to the graph. * * Returns: None. * Side effects: None. */ static void uber_line_graph_render_line (UberLineGraph *graph, /* IN */ cairo_t *cr, /* IN */ GdkRectangle *area, /* IN */ LineInfo *line, /* IN */ guint epoch, /* IN */ gfloat each) /* IN */ { UberLineGraphPrivate *priv; UberRange pixel_range; GdkRectangle vis; guint x; guint last_x; gdouble y; gdouble last_y; gdouble val; gint i; g_return_if_fail(UBER_IS_LINE_GRAPH(graph)); priv = graph->priv; uber_graph_get_content_area(UBER_GRAPH(graph), &vis); pixel_range.begin = area->y + 1; pixel_range.end = area->y + area->height; pixel_range.range = pixel_range.end - pixel_range.begin; /* * Prepare cairo settings. */ uber_line_graph_stylize_line(graph, line, cr); /* * Force a new path. */ cairo_new_path(cr); /* * Draw the line contents as bezier curves. */ for (i = 0; i < line->raw_data->len; i++) { /* * Retrieve data point. */ val = g_ring_get_index(line->raw_data, gdouble, i); /* * Once we get to -INFINITY, we must be at the end of the data * sequence. This may not always be true in the future. */ if (val == -INFINITY) { break; } /* * Translate value to coordinate system. */ if (!priv->scale(&priv->range, &pixel_range, &val, priv->scale_data)) { break; } /* * Calculate X/Y coordinate. */ y = (gint)(RECT_BOTTOM(*area) - val) - .5; x = epoch - (each * i); if (i == 0) { /* * Just move to the right position on first entry. */ cairo_move_to(cr, x, y); goto next; } else { /* * Draw curve to data point using the last X/Y positions as * control points. */ cairo_curve_to(cr, last_x - (each / 2.), last_y, last_x - (each / 2.), y, x, y); } next: last_y = y; last_x = x; } /* * Stroke the line content. */ cairo_stroke(cr); }