Re: plot data stream in realtime



Well I wrote an extension, a little hackish for now, using Dave Amish's option
...
3. dynamically growing arrays
...
It uses growing GArrays and converts it to gfloat* when we need to talk "GtkDataboxese". I'm using this on a project of mine (http://i.imgur.com/s585f.png) and the result is as expected. The only thing that needs to be done from the "outside" is updating the GtkDatabox (redrawing it). Like connecting the "notify::length" signal to a simple function to handle a rescale (hack to make it work I'm actually using).

The attached code is somewhat a rewrite of the original gtkdatabox_xyc_graph and gtkdatabox_lines with added push_point and some NULL pointers safety. To use it in any project:

{
...

/* Create the databox as usual */
GtkWidget *table;
GtkWidget *box;
gtk_databox_create_box_with_scrollbars_and_rulers(
                &box, &table, TRUE, TRUE, TRUE, TRUE);

/* Set a color for the graph */
GdkColor color;
color.red = 0;
color.green = 0;
color.blue = 0;

/* create two GArrays, this step is not neccessary as the push_point
 * function will do that if they are NULL ;) */
GArray *X = g_array_new(FALSE, FALSE, sizeof (gfloat));
GArray *Y = g_array_new(FALSE, FALSE, sizeof (gfloat));

/* create the graph */
graph = gtk_databox_rt_lines_new(X, Y, &color, 1);

/* make sure of removing the self reference ;) */
g_array_unref(X);
g_array_unref(Y);

/* add it to the box */
gtk_databox_graph_add(GTK_DATABOX(box), graph);

/* add a signal to update the graph if neccesary */
g_signal_connect(graph, "notify::length",
                G_CALLBACK(redraw_graph), GTK_DATABOX(box));

...
}


Then I added this single function to redraw each time:

static void
redraw_graph (GtkDataboxGraph  *graph,
                        gint             len,
                        GtkDatabox       *box)
{
    gtk_databox_auto_rescale(GTK_DATABOX(box), 0.05);
}


To Add the data call:
gtk_databox_rt_xyc_graph_push_point(graph, x_point, y_point);

I would suggest again to move the entire API to a GArray based one (we can have a compatibility layer for existing code) they are fast and really easy to manage, and would be more effective in this RT cases and can be used for static graphs too.
The GtkDatabox can be provided with means to manage automatic redraws by connecting internally to it's child "lenght" property and queue a redraw (invalidate it's own rectagle).

Is it worth a meeting on IRC to talk this stuff (new features, new developers, coding standars, repository updates, porting to GTK3, etc.)? Since there is more movement in the mailing list than the codebase, with a lot of patches and code and little getting into de repository, we can chat about it on freenode or sth.

Btw: this code is done in GTK2 and is not ported to GTK3 as the only working configuration I have right now is GTK2 :(

Cya guys and best regards! :)

Joaquín Aramendía

PS: I added the screenshot to img.ur to fit the message quota


/*
 * Copyright (c) 2012,
 * Author: Joaquín Ignacio Aramendía (samsagax) <samsagax [at] gmail [dot] com>
 *
 * This file is part of PROJECTNAME.
 *
 * PROJECTNAME is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PROJECTNAME is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PROJECTNAME. If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * gtkdatabox_rt_lines.c :
 */

#include "gtkdatabox_rt_lines.h"

static void gtk_databox_rt_lines_dispose    (GObject        *object);

static void gtk_databox_rt_lines_finalize   (GObject        *object);

static void gtk_databox_rt_lines_real_draw (GtkDataboxGraph *lines,
					                        GtkDatabox      *box);

/* Private structure */
typedef struct _GtkDataboxRTLinesPrivate GtkDataboxRTLinesPrivate;
struct _GtkDataboxRTLinesPrivate {
    GdkPoint *points;
};

/* Register new type */
G_DEFINE_TYPE(GtkDataboxRTLines, gtk_databox_rt_lines, GTK_DATABOX_TYPE_RT_XYC_GRAPH);

/* Implementation */
static void
gtk_databox_rt_lines_class_init (GtkDataboxRTLinesClass *klass)
{
    GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
    GtkDataboxGraphClass *graph_class = GTK_DATABOX_GRAPH_CLASS(klass);

    /* Dispose and Finalize functions */
    gobject_class->dispose = gtk_databox_rt_lines_dispose;
    gobject_class->finalize = gtk_databox_rt_lines_finalize;

    /* Override draw */
    graph_class->draw = gtk_databox_rt_lines_real_draw;

    g_type_class_add_private (klass, sizeof(GtkDataboxRTLinesPrivate));
}

static void
gtk_databox_rt_lines_update_length(GtkDataboxRTLines *rt_lines)
{
    GtkDataboxRTLinesPrivate *priv =
        GTK_DATABOX_RT_LINES_GET_PRIVATE(rt_lines);
    priv->points = g_renew(GdkPoint, priv->points,
            gtk_databox_rt_xyc_graph_get_length(
                GTK_DATABOX_RT_XYC_GRAPH(rt_lines)));
}

static void
gtk_databox_rt_lines_init (GtkDataboxRTLines *rt_lines)
{
    GtkDataboxRTLinesPrivate *priv =
        GTK_DATABOX_RT_LINES_GET_PRIVATE(rt_lines);
    g_signal_connect (rt_lines, "notify::length",
            G_CALLBACK(gtk_databox_rt_lines_update_length), NULL);
}

static void
gtk_databox_rt_lines_dispose (GObject   *gobject)
{
    /* Chain-Up */
    G_OBJECT_CLASS(gtk_databox_rt_lines_parent_class)->dispose(gobject);
}

static void
gtk_databox_rt_lines_finalize (GObject   *gobject)
{
    g_free (GTK_DATABOX_RT_LINES_GET_PRIVATE(gobject)->points);

    /* Chain-Up */
    G_OBJECT_CLASS(gtk_databox_rt_lines_parent_class)->finalize(gobject);
}

static void
gtk_databox_rt_lines_real_draw (GtkDataboxGraph     *graph,
			                    GtkDatabox          *box)
{
    g_return_if_fail (GTK_DATABOX_IS_RT_LINES (graph));
    g_return_if_fail (GTK_IS_DATABOX (box));

    GtkWidget *widget;
    GtkDataboxRTLines *rt_lines;
    GdkPoint *points;
    GdkPixmap *pixmap;
    GtkStyle *style;
    GdkGC *gc;
    guint i = 0;
    gfloat *float_X;
    gfloat *float_Y;
    guint len;
    gint size = 0;

    rt_lines = GTK_DATABOX_RT_LINES (graph);
    widget = GTK_WIDGET(box);

    pixmap = gtk_databox_get_backing_pixmap (box);
    style = widget->style;

    if (!(gc = gtk_databox_graph_get_gc(graph))) {
        gc = gtk_databox_graph_create_gc (graph, box);
    }

    len = gtk_databox_rt_xyc_graph_get_length (GTK_DATABOX_RT_XYC_GRAPH (graph));
    float_X = gtk_databox_rt_xyc_graph_get_float_X (GTK_DATABOX_RT_XYC_GRAPH (graph));
    float_Y = gtk_databox_rt_xyc_graph_get_float_Y (GTK_DATABOX_RT_XYC_GRAPH (graph));
    /* Check for something to draw */
    if(float_X == NULL || float_Y == NULL || len == 0) {
        return;
    }

    size = gtk_databox_graph_get_size (graph);
    points = GTK_DATABOX_RT_LINES_GET_PRIVATE(graph)->points;

    /* Here we need to talk GtkDataboxese */
    gtk_databox_values_to_pixels (box, len, float_X, float_Y, points);

    /* More than 2^16 lines will cause X IO error on most XServers
       (Hint from Paul Barton-Davis) */
    for (i = 0; i < len; i += 65536) {
        gdk_draw_lines (pixmap, gc, points + i,
                MIN (65536, len - i));
    }

    return;
}

/* Public API */
GtkDataboxGraph*
gtk_databox_rt_lines_new (GArray    *X,
                          GArray    *Y,
                          GdkColor  *color,
                          guint     size)
{
    GtkDataboxGraph *rt_lines;

    rt_lines = g_object_new (GTK_DATABOX_TYPE_RT_LINES,
                                "X", X,
                                "Y", Y,
                                "color", color,
                                "size", size,
                                NULL);

    return rt_lines;
}

/*
 * Copyright (c) 2012, Joaquín Ignacio Aramendía
 * Author: Joaquín Ignacio Aramendía <samsagax [at] gmail [dot] com>
 *
 * This file is part of PROJECTNAME.
 *
 * PROJECTNAME is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PROJECTNAME is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PROJECTNAME. If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * gtkdatabox_rt_lines.h: Extension to GtkDatabox to plot lines in real
 * time using growing GArrays.
 */


#ifndef  GTK_DATABOX_RT_LINES_INC
#define  GTK_DATABOX_RT_LINES_INC

#include <gtkdatabox_rt_xyc_graph.h>

#define GTK_DATABOX_TYPE_RT_LINES             (gtk_databox_rt_lines_get_type())
#define GTK_DATABOX_RT_LINES(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_DATABOX_TYPE_RT_LINES, GtkDataboxRTLines))
#define GTK_DATABOX_IS_RT_LINES(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_DATABOX_TYPE_RT_LINES))
#define GTK_DATABOX_RT_LINES_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_DATABOX_TYPE_RT_LINES, GtkDataboxRTLinesClass))
#define GTK_DATABOX_IS_RT_LINES_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_DATABOX_TYPE_RT_LINES))
#define GTK_DATABOX_RT_LINES_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_DATABOX_TYPE_RT_LINES, GtkDataboxRTLinesClass))
#define GTK_DATABOX_RT_LINES_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_DATABOX_TYPE_RT_LINES, GtkDataboxRTLinesPrivate))

typedef struct _GtkDataboxRTLines GtkDataboxRTLines;
typedef struct _GtkDataboxRTLinesClass GtkDataboxRTLinesClass;

struct _GtkDataboxRTLines {
    GtkDataboxRTXYCGraph          parent;
};

struct _GtkDataboxRTLinesClass {
    GtkDataboxRTXYCGraphClass     parent_class;
};

/* Methods */
GType               gtk_databox_rt_lines_get_type   (void);

GtkDataboxGraph*    gtk_databox_rt_lines_new        (GArray     *X,
                                                     GArray     *Y,
                                                     GdkColor   *color,
                                                     guint      size);

#endif   /* ----- #ifndef GTK_DATABOX_RT_LINES_INC  ----- */

/*
 * Copyright (c) 2012,
 * Author: Joaquín Ignacio Aramendía (samsagax) <samsagax [at] gmail [dot] com>
 *
 * This file is part of PROJECTNAME.
 *
 * PROJECTNAME is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PROJECTNAME is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PROJECTNAME. If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * gtkdatabox_rt_xyc_graph.c :
 */

#include "gtkdatabox_rt_xyc_graph.h"

static void gtk_databox_rt_xyc_graph_dispose (GObject *object);

static void gtk_databox_rt_xyc_graph_finalize (GObject *object);

static gint gtk_databox_rt_xyc_graph_real_calculate_extrema
                (GtkDataboxGraph *rt_xyc_graph,
                 gfloat *min_x,
                 gfloat *max_x,
                 gfloat *min_y,
                 gfloat *max_y);

/* Properties IDs */
enum {
    PROP_X = 1,
    PROP_Y,
    PROP_FLOAT_X,
    PROP_FLOAT_Y,
    PROP_LEN,
    N_PROPERTIES
};
static GParamSpec *rt_xyc_graph_properties[N_PROPERTIES] = { NULL, };

/* Private structure */
typedef struct _GtkDataboxRTXYCGraphPrivate GtkDataboxRTXYCGraphPrivate;
struct _GtkDataboxRTXYCGraphPrivate {
    GArray  *X;
    GArray  *Y;

    /* Hold this to talk GtkDataboxese */
    gfloat  *float_X;
    gfloat  *float_Y;
};

/* Register new type */
G_DEFINE_TYPE(GtkDataboxRTXYCGraph, gtk_databox_rt_xyc_graph, GTK_DATABOX_TYPE_GRAPH);

/* Implementation */
static void
gtk_databox_rt_xyc_graph_set_X (GtkDataboxRTXYCGraph    *rt_xyc_graph,
                                GArray                  *x)
{
    g_return_if_fail(GTK_DATABOX_IS_RT_XYC_GRAPH(rt_xyc_graph));
//    g_return_if_fail(x);

    GArray *X = GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(rt_xyc_graph)->X;
    if(X != NULL) {
        g_array_free(X, FALSE);
    }
    X = g_array_ref(x);

    g_object_notify (G_OBJECT(rt_xyc_graph), "X-Values");
    g_object_notify (G_OBJECT(rt_xyc_graph), "X");
}

static void
gtk_databox_rt_xyc_graph_set_Y (GtkDataboxRTXYCGraph    *rt_xyc_graph,
                                GArray                  *y)
{
    g_return_if_fail(GTK_DATABOX_IS_RT_XYC_GRAPH(rt_xyc_graph));
//    g_return_if_fail(y);

    GArray *Y = GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(rt_xyc_graph)->Y;
    if(Y != NULL) {
        g_array_free(Y, FALSE);
    }
    Y = g_array_ref(y);

    g_object_notify (G_OBJECT(rt_xyc_graph), "Y-Values");
    g_object_notify (G_OBJECT(rt_xyc_graph), "Y");
}

static void
gtk_databox_rt_xyc_graph_set_length (GtkDataboxRTXYCGraph   *rt_xyc_graph,
                                     guint                  len)
{
    g_return_if_fail (GTK_DATABOX_IS_RT_XYC_GRAPH (rt_xyc_graph));
    g_return_if_fail (len > 0);

    GtkDataboxRTXYCGraphPrivate *priv = GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(rt_xyc_graph);

    g_array_set_size(priv->X, len);
    g_array_set_size(priv->Y, len);

    g_object_notify (G_OBJECT (rt_xyc_graph), "length");
}

GArray*
gtk_databox_rt_xyc_graph_get_X (GtkDataboxRTXYCGraph    *rt_xyc_graph)
{
    g_return_val_if_fail (GTK_DATABOX_IS_RT_XYC_GRAPH(rt_xyc_graph), NULL);

    return GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(rt_xyc_graph)->X;
}

GArray*
gtk_databox_rt_xyc_graph_get_Y (GtkDataboxRTXYCGraph    *rt_xyc_graph)
{
    g_return_val_if_fail (GTK_DATABOX_IS_RT_XYC_GRAPH(rt_xyc_graph), NULL);

    return GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(rt_xyc_graph)->Y;
}

gfloat*
gtk_databox_rt_xyc_graph_get_float_X (GtkDataboxRTXYCGraph  *rt_xyc_graph)
{
    g_return_val_if_fail (GTK_DATABOX_IS_RT_XYC_GRAPH(rt_xyc_graph), NULL);

    GtkDataboxRTXYCGraphPrivate *priv =
        GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(rt_xyc_graph);
    guint len = gtk_databox_rt_xyc_graph_get_length(rt_xyc_graph);
    if (len == 0) {
        return NULL;
    }
    guint i;
    if (priv->float_X == NULL) {
        priv->float_X = g_new(gfloat, len);
    } else {
        priv->float_X = g_renew(gfloat, priv->float_X, len);
    }
    for (i = 0; i < len; i++) {
        priv->float_X[i] = g_array_index(priv->X, gfloat, i);
    }

    return priv->float_X;
}

gfloat*
gtk_databox_rt_xyc_graph_get_float_Y (GtkDataboxRTXYCGraph  *rt_xyc_graph)
{
    g_return_val_if_fail (GTK_DATABOX_IS_RT_XYC_GRAPH(rt_xyc_graph), NULL);

    GtkDataboxRTXYCGraphPrivate *priv =
        GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(rt_xyc_graph);
    gint len = gtk_databox_rt_xyc_graph_get_length(rt_xyc_graph);
    if (len == 0) {
        return NULL;
    }
    guint i;
    if (priv->float_Y == NULL) {
        priv->float_Y = g_new(gfloat, len);
    } else {
        priv->float_Y = g_renew(gfloat, priv->float_Y, len);
    }
    for (i = 0; i < len; i++) {
        priv->float_Y[i] = g_array_index(priv->Y, gfloat, i);
    }

    return priv->float_Y;
}

guint
gtk_databox_rt_xyc_graph_get_length (GtkDataboxRTXYCGraph   *rt_xyc_graph)
{
    g_return_val_if_fail (GTK_DATABOX_IS_RT_XYC_GRAPH(rt_xyc_graph), 0);

    GtkDataboxRTXYCGraphPrivate *priv =
        GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(rt_xyc_graph);
    if (priv->X == NULL || priv->Y == NULL) {
        return 0;
    }

    return priv->X->len;
}

static void
gtk_databox_rt_xyc_graph_set_property (GObject      *object,
                                       guint        prop_id,
                                       const GValue *value,
                                       GParamSpec   *param)
{
    GtkDataboxRTXYCGraph *rt_xyc_graph = GTK_DATABOX_RT_XYC_GRAPH(object);

    switch (prop_id) {
        case PROP_X:
            {
                gtk_databox_rt_xyc_graph_set_X(rt_xyc_graph,
                        (GArray*)(g_value_get_pointer(value)));
            }
            break;
        case PROP_Y:
            {
                gtk_databox_rt_xyc_graph_set_Y(rt_xyc_graph,
                        (GArray*)(g_value_get_pointer(value)));
            }
            break;
        case PROP_LEN:
            {
                gtk_databox_rt_xyc_graph_set_length(rt_xyc_graph,
                        g_value_get_int(value));
            }
            break;
        default:
            /* Unknown property */
            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, param);
            break;
    }
}

static void
gtk_databox_rt_xyc_graph_get_property (GObject      *object,
                                       guint        prop_id,
                                       GValue       *value,
                                       GParamSpec   *params)
{
    GtkDataboxRTXYCGraph *rt_xyc_graph = GTK_DATABOX_RT_XYC_GRAPH(object);

    switch (prop_id) {
        case PROP_X:
            {
                g_value_set_pointer(value,
                        gtk_databox_rt_xyc_graph_get_X(rt_xyc_graph));
            }
            break;
        case PROP_Y:
            {
                g_value_set_pointer(value,
                        gtk_databox_rt_xyc_graph_get_Y(rt_xyc_graph));
            }
            break;
        case PROP_LEN:
            {
                g_value_set_int(value,
                        gtk_databox_rt_xyc_graph_get_length(rt_xyc_graph));
            }
            break;
        case PROP_FLOAT_X:
            {
                g_value_set_pointer(value,
                        gtk_databox_rt_xyc_graph_get_float_X(rt_xyc_graph));
            }
            break;
        case PROP_FLOAT_Y:
            {
                g_value_set_pointer(value,
                        gtk_databox_rt_xyc_graph_get_float_Y(rt_xyc_graph));
            }
            break;
        default:
            /* Unknown property */
            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, params);
    }
}

static void
gtk_databox_rt_xyc_graph_class_init (GtkDataboxRTXYCGraphClass *klass)
{
    GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
    GtkDataboxGraphClass *graph_class = GTK_DATABOX_GRAPH_CLASS(klass);

    /* Setup properties */
    gobject_class->set_property = gtk_databox_rt_xyc_graph_set_property;
    gobject_class->get_property = gtk_databox_rt_xyc_graph_get_property;

    rt_xyc_graph_properties[PROP_FLOAT_X] =
                            g_param_spec_pointer("X-Values",
                                "X Coordinates",
                                "X floating-point data values",
                                G_PARAM_READABLE);
    rt_xyc_graph_properties[PROP_FLOAT_Y] =
                            g_param_spec_pointer("Y-Values",
                                "Y Coordinates",
                                "Y floating-point data values",
                                G_PARAM_READABLE);
    rt_xyc_graph_properties[PROP_X] =
                            g_param_spec_pointer("X",
                                "X Coordinates",
                                "Garray data values in X",
                                G_PARAM_READWRITE |
                                G_PARAM_CONSTRUCT);
    rt_xyc_graph_properties[PROP_Y] =
                            g_param_spec_pointer("Y",
                                "Y Coordinates",
                                "Garray data values in Y",
                                G_PARAM_READWRITE |
                                G_PARAM_CONSTRUCT);
    rt_xyc_graph_properties[PROP_LEN] =
                            g_param_spec_int("length",
                                "length of X and Y",
                                "number of data points",
                                G_MININT,
                                G_MAXINT,
                                0,
                                G_PARAM_READWRITE);
    g_object_class_install_properties(gobject_class,
                                N_PROPERTIES,
                                rt_xyc_graph_properties);

    /* Dispose and Finalize functions */
    gobject_class->dispose = gtk_databox_rt_xyc_graph_dispose;
    gobject_class->finalize = gtk_databox_rt_xyc_graph_finalize;

    /* Override calculate_extrema */
    graph_class->calculate_extrema = gtk_databox_rt_xyc_graph_real_calculate_extrema;

    g_type_class_add_private (klass, sizeof(GtkDataboxRTXYCGraphPrivate));
}

static void
gtk_databox_rt_xyc_graph_init (GtkDataboxRTXYCGraph *rt_xyc_graph)
{
    GtkDataboxRTXYCGraphPrivate *priv =
        GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(rt_xyc_graph);
    priv->X = NULL;
    priv->Y = NULL;
    priv->float_X = NULL;
    priv->float_Y = NULL;
}

static gint
gtk_databox_rt_xyc_graph_real_calculate_extrema (GtkDataboxGraph    *graph,
                                                 gfloat             *min_x,
                                                 gfloat             *max_x,
                                                 gfloat             *min_y,
                                                 gfloat             *max_y)
{
    GtkDataboxRTXYCGraph *rt_xyc_graph = GTK_DATABOX_RT_XYC_GRAPH(graph);
    GtkDataboxRTXYCGraphPrivate *priv =
        GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(rt_xyc_graph);
    gint len = gtk_databox_rt_xyc_graph_get_length(rt_xyc_graph);
    if (priv->X == NULL || priv->Y == NULL || len == 0) {
        *min_x = *max_x = *min_y = *max_y = 0;
        g_print("extrema can't be calculated \n");
        return -2;
    }

    guint i;
    gfloat x, y;
    *min_x = *max_x = g_array_index(priv->X, gfloat, 0);
    *min_y = *max_y = g_array_index(priv->Y, gfloat, 0);

    for(i = 1; i < len; i++) {
        x = g_array_index(priv->X, gfloat, i);
        y = g_array_index(priv->Y, gfloat, i);
        if (x < *min_x) {
            *min_x = x;
        } else if (x > *max_x) {
            *max_x = x;
        }
        if (y < *min_y) {
            *min_y = y;
        } else if (y > *max_y) {
            *max_y = y;
        }
    }

    g_print("extrema calculated successfuly \n");
    return 0;
}

static void
gtk_databox_rt_xyc_graph_dispose (GObject   *gobject)
{
    /* Chain-Up */
    G_OBJECT_CLASS(gtk_databox_rt_xyc_graph_parent_class)->dispose(gobject);
}

static void
gtk_databox_rt_xyc_graph_finalize (GObject   *gobject)
{
    g_array_free(GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(gobject)->X, FALSE);
    g_array_free(GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(gobject)->Y, FALSE);
    g_free(GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(gobject)->float_X);
    g_free(GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(gobject)->float_Y);

    /* Chain-Up */
    G_OBJECT_CLASS(gtk_databox_rt_xyc_graph_parent_class)->finalize(gobject);
}

void
gtk_databox_rt_xyc_graph_push_point (GtkDataboxRTXYCGraph   *rt_xyc_graph,
                                     gfloat                 x,
                                     gfloat                 y)
{
    g_return_if_fail(GTK_DATABOX_IS_RT_XYC_GRAPH(rt_xyc_graph));

    GtkDataboxRTXYCGraphPrivate *priv =
        GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(rt_xyc_graph);
    if(priv->X == NULL) {
        priv->X = g_array_new(FALSE, FALSE, sizeof(gfloat));
    }
    if(priv->Y == NULL) {
        priv->Y = g_array_new(FALSE, FALSE, sizeof(gfloat));
    }
    g_array_append_val(
            GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(rt_xyc_graph)->X, x);
    g_array_append_val(
            GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(rt_xyc_graph)->Y, y);

    g_object_notify(G_OBJECT(rt_xyc_graph), "X");
    g_object_notify(G_OBJECT(rt_xyc_graph), "Y");
    g_object_notify(G_OBJECT(rt_xyc_graph), "X-Values");
    g_object_notify(G_OBJECT(rt_xyc_graph), "Y-Values");
    g_object_notify(G_OBJECT(rt_xyc_graph), "length");
}

/*
 * Copyright (c) 2012, Joaquín Ignacio Aramendía
 * Author: Joaquín Ignacio Aramendía <samsagax [at] gmail [dot] com>
 *
 * This file is part of PROJECTNAME.
 *
 * PROJECTNAME is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PROJECTNAME is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PROJECTNAME. If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * gtkdatabox_rt_xyc_graph.h: Extension to GtkDatabox to plot in real
 * time using GArrays.
 */


#ifndef  GTK_DATABOX_RT_XYC_GRAPH_INC
#define  GTK_DATABOX_RT_XYC_GRAPH_INC

#include <gtkdatabox_graph.h>

#define GTK_DATABOX_TYPE_RT_XYC_GRAPH             (gtk_databox_rt_xyc_graph_get_type())
#define GTK_DATABOX_RT_XYC_GRAPH(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_DATABOX_TYPE_RT_XYC_GRAPH, GtkDataboxRTXYCGraph))
#define GTK_DATABOX_IS_RT_XYC_GRAPH(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_DATABOX_TYPE_RT_XYC_GRAPH))
#define GTK_DATABOX_RT_XYC_GRAPH_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_DATABOX_TYPE_RT_XYC_GRAPH, GtkDataboxRTXYCGraphClass))
#define GTK_DATABOX_IS_RT_XYC_GRAPH_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_DATABOX_TYPE_RT_XYC_GRAPH))
#define GTK_DATABOX_RT_XYC_GRAPH_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_DATABOX_TYPE_RT_XYC_GRAPH, GtkDataboxRTXYCGraphClass))
#define GTK_DATABOX_RT_XYC_GRAPH_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_DATABOX_TYPE_RT_XYC_GRAPH, GtkDataboxRTXYCGraphPrivate))

typedef struct _GtkDataboxRTXYCGraph GtkDataboxRTXYCGraph;
typedef struct _GtkDataboxRTXYCGraphClass GtkDataboxRTXYCGraphClass;

struct _GtkDataboxRTXYCGraph {
    GtkDataboxGraph          parent;
};

struct _GtkDataboxRTXYCGraphClass {
    GtkDataboxGraphClass     parent_class;
};

/* Methods */

GType       gtk_databox_rt_xyc_graph_get_type   (void);

guint       gtk_databox_rt_xyc_graph_get_length     (GtkDataboxRTXYCGraph *rt_xyc_graph);

GArray*     gtk_databox_rt_xyc_graph_get_X          (GtkDataboxRTXYCGraph *rt_xyc_graph);

GArray*     gtk_databox_rt_xyc_graph_get_Y          (GtkDataboxRTXYCGraph *rt_xyc_graph);

gfloat*     gtk_databox_rt_xyc_graph_get_float_X    (GtkDataboxRTXYCGraph *rt_xyc_graph);

gfloat*     gtk_databox_rt_xyc_graph_get_float_Y    (GtkDataboxRTXYCGraph *rt_xyc_graph);

void        gtk_databox_rt_xyc_graph_push_point     (GtkDataboxRTXYCGraph *rt_xyc_graph,
                                                     gfloat               x,
                                                     gfloat               y);

#endif   /* ----- #ifndef GTK_DATABOX_RT_XYC_GRAPH_INC  ----- */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]