"Fossies" - the Fresh Open Source Software Archive

Member "gtkdatabox-1.0.0/gtk/gtkdatabox_xyyc_graph.c" (31 Mar 2021, 29218 Bytes) of package /linux/privat/gtkdatabox-1.0.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "gtkdatabox_xyyc_graph.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.9.3.1_vs_1.0.0.

    1 /* $Id: gtkdatabox_xyyc_graph.c 4 2008-06-22 09:19:11Z rbock $ */
    2 /* GtkDatabox - An extension to the gtk+ library
    3  * Copyright (C) 1998 - 2008  Dr. Roland Bock
    4  * Copyright (C) 2012  Dr. Matt Flax <flatmax@>
    5  *
    6  * This program is free software; you can redistribute it and/or
    7  * modify it under the terms of the GNU Lesser General Public License
    8  * as published by the Free Software Foundation; either version 2.1
    9  * of the License, or (at your option) any later version.
   10  *
   11  * This program is distributed in the hope that it will be useful,
   12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  * GNU Lesser General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU General Public License
   17  * along with this program; if not, write to the Free Software
   18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   19  */
   20 
   21 #include <gtkdatabox_xyyc_graph.h>
   22 
   23 static gint gtk_databox_xyyc_graph_real_calculate_extrema (GtkDataboxGraph *
   24                               xyyc_graph,
   25                               gfloat * min_x,
   26                               gfloat * max_x,
   27                               gfloat * min_y,
   28                               gfloat * max_y);
   29 
   30 /* IDs of properties */
   31 enum
   32 {
   33    PROP_X = 1,
   34    PROP_Y1,
   35    PROP_Y2,
   36    PROP_LEN,
   37    PROP_SIZE,
   38    PROP_XSTART,
   39    PROP_Y1START,
   40    PROP_Y2START,
   41    PROP_XSTRIDE,
   42    PROP_Y1STRIDE,
   43    PROP_Y2STRIDE,
   44    PROP_XTYPE,
   45    PROP_YTYPE
   46 };
   47 
   48 /**
   49  * GtkDataboxXYYCGraphPrivate
   50  *
   51  * A private data structure used by the #GtkDataboxXYYCGraph. It shields all internal things
   52  * from developers who are just using the object.
   53  *
   54  **/
   55 typedef struct _GtkDataboxXYYCGraphPrivate GtkDataboxXYYCGraphPrivate;
   56 
   57 struct _GtkDataboxXYYCGraphPrivate
   58 {
   59    gfloat *X;
   60    gfloat *Y1;
   61    gfloat *Y2;
   62    guint len;
   63    guint maxlen;
   64    guint xstart;
   65    guint y1start;
   66    guint y2start;
   67    guint xstride;
   68    guint y1stride;
   69    guint y2stride;
   70    GType xtype;
   71    GType ytype;
   72 };
   73 
   74 G_DEFINE_TYPE_WITH_PRIVATE(GtkDataboxXYYCGraph, gtk_databox_xyyc_graph,
   75     GTK_DATABOX_TYPE_GRAPH)
   76 
   77 static void
   78 gtk_databox_xyyc_graph_set_X (GtkDataboxXYYCGraph * xyyc_graph, gfloat * X)
   79 {
   80    g_return_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph));
   81    g_return_if_fail (X);
   82    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
   83    priv->X = X;
   84 
   85    g_object_notify (G_OBJECT (xyyc_graph), "X-Values");
   86 }
   87 
   88 static void
   89 gtk_databox_xyyc_graph_set_Y1 (GtkDataboxXYYCGraph * xyyc_graph, gfloat * Y1)
   90 {
   91    g_return_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph));
   92    g_return_if_fail (Y1);
   93    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
   94    priv->Y1 = Y1;
   95 
   96    g_object_notify (G_OBJECT (xyyc_graph), "Y1-Values");
   97 }
   98 
   99 static void
  100 gtk_databox_xyyc_graph_set_Y2 (GtkDataboxXYYCGraph * xyyc_graph, gfloat * Y2)
  101 {
  102    g_return_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph));
  103    g_return_if_fail (Y2);
  104    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  105    priv->Y2 = Y2;
  106 
  107    g_object_notify (G_OBJECT (xyyc_graph), "Y2-Values");
  108 }
  109 
  110 static void
  111 gtk_databox_xyyc_graph_set_length (GtkDataboxXYYCGraph * xyyc_graph, guint len)
  112 {
  113    g_return_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph));
  114    g_return_if_fail (len > 0);
  115    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  116    priv->len = len;
  117 
  118    g_object_notify (G_OBJECT (xyyc_graph), "length");
  119 }
  120 
  121 static void
  122 gtk_databox_xyyc_graph_set_maxlen (GtkDataboxXYYCGraph * xyyc_graph, guint maxlen)
  123 {
  124    g_return_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph));
  125    g_return_if_fail (maxlen > 0);
  126    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  127    priv->maxlen = maxlen;
  128 
  129    g_object_notify (G_OBJECT (xyyc_graph), "maxlen");
  130 }
  131 
  132 static void
  133 gtk_databox_xyyc_graph_set_xstart (GtkDataboxXYYCGraph * xyyc_graph, guint xstart)
  134 {
  135    g_return_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph));
  136    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  137    priv->xstart = xstart;
  138 
  139    g_object_notify (G_OBJECT (xyyc_graph), "X-Values");
  140 }
  141 
  142 static void
  143 gtk_databox_xyyc_graph_set_y1start (GtkDataboxXYYCGraph * xyyc_graph, guint y1start)
  144 {
  145    g_return_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph));
  146    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  147    priv->y1start = y1start;
  148 
  149    g_object_notify (G_OBJECT (xyyc_graph), "Y1-Values");
  150 }
  151 
  152 static void
  153 gtk_databox_xyyc_graph_set_y2start (GtkDataboxXYYCGraph * xyyc_graph, guint y2start)
  154 {
  155    g_return_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph));
  156    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  157    priv->y2start = y2start;
  158 
  159    g_object_notify (G_OBJECT (xyyc_graph), "Y2-Values");
  160 }
  161 
  162 static void
  163 gtk_databox_xyyc_graph_set_xstride (GtkDataboxXYYCGraph * xyyc_graph, guint xstride)
  164 {
  165    g_return_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph));
  166    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  167    priv->xstride = xstride;
  168 
  169    g_object_notify (G_OBJECT (xyyc_graph), "X-Values");
  170 }
  171 
  172 static void
  173 gtk_databox_xyyc_graph_set_y1stride (GtkDataboxXYYCGraph * xyyc_graph, guint y1stride)
  174 {
  175    g_return_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph));
  176    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  177    priv->y1stride = y1stride;
  178 
  179    g_object_notify (G_OBJECT (xyyc_graph), "Y1-Values");
  180 }
  181 
  182 static void
  183 gtk_databox_xyyc_graph_set_y2stride (GtkDataboxXYYCGraph * xyyc_graph, guint y2stride)
  184 {
  185    g_return_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph));
  186    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  187    priv->y2stride = y2stride;
  188 
  189    g_object_notify (G_OBJECT (xyyc_graph), "Y2-Values");
  190 }
  191 
  192 static void
  193 gtk_databox_xyyc_graph_set_xtype (GtkDataboxXYYCGraph * xyyc_graph, GType xtype)
  194 {
  195    g_return_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph));
  196    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  197    priv->xtype = xtype;
  198 
  199    g_object_notify (G_OBJECT (xyyc_graph), "X-Values");
  200 }
  201 
  202 static void
  203 gtk_databox_xyyc_graph_set_ytype (GtkDataboxXYYCGraph * xyyc_graph, GType ytype)
  204 {
  205    g_return_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph));
  206    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  207    priv->ytype = ytype;
  208 
  209    g_object_notify (G_OBJECT (xyyc_graph), "Y1-Values");
  210    g_object_notify (G_OBJECT (xyyc_graph), "Y2-Values");
  211 }
  212 
  213 static void
  214 gtk_databox_xyyc_graph_set_property (GObject * object,
  215                     guint property_id,
  216                     const GValue * value, GParamSpec * pspec)
  217 {
  218    GtkDataboxXYYCGraph *xyyc_graph = GTK_DATABOX_XYYC_GRAPH (object);
  219 
  220    switch (property_id)
  221    {
  222    case PROP_X:
  223       gtk_databox_xyyc_graph_set_X (xyyc_graph, (gfloat *) g_value_get_pointer (value));
  224       break;
  225    case PROP_Y1:
  226       gtk_databox_xyyc_graph_set_Y1 (xyyc_graph, (gfloat *) g_value_get_pointer (value));
  227       break;
  228    case PROP_Y2:
  229       gtk_databox_xyyc_graph_set_Y2 (xyyc_graph, (gfloat *) g_value_get_pointer (value));
  230       break;
  231    case PROP_LEN:
  232       gtk_databox_xyyc_graph_set_length (xyyc_graph, g_value_get_int (value));
  233       break;
  234    case PROP_SIZE:
  235       gtk_databox_xyyc_graph_set_maxlen (xyyc_graph, g_value_get_int (value));
  236       break;
  237    case PROP_XSTART:
  238       gtk_databox_xyyc_graph_set_xstart (xyyc_graph, g_value_get_int (value));
  239       break;
  240    case PROP_Y1START:
  241       gtk_databox_xyyc_graph_set_y1start (xyyc_graph, g_value_get_int (value));
  242       break;
  243    case PROP_Y2START:
  244       gtk_databox_xyyc_graph_set_y2start (xyyc_graph, g_value_get_int (value));
  245       break;
  246    case PROP_XSTRIDE:
  247       gtk_databox_xyyc_graph_set_xstride (xyyc_graph, g_value_get_int (value));
  248       break;
  249    case PROP_Y1STRIDE:
  250       gtk_databox_xyyc_graph_set_y1stride (xyyc_graph, g_value_get_int (value));
  251       break;
  252    case PROP_Y2STRIDE:
  253       gtk_databox_xyyc_graph_set_y2stride (xyyc_graph, g_value_get_int (value));
  254       break;
  255    case PROP_XTYPE:
  256       gtk_databox_xyyc_graph_set_xtype (xyyc_graph, g_value_get_gtype (value));
  257       break;
  258    case PROP_YTYPE:
  259       gtk_databox_xyyc_graph_set_ytype (xyyc_graph, g_value_get_gtype (value));
  260       break;
  261    default:
  262       /* We don't have any other property... */
  263       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  264       break;
  265    }
  266 }
  267 
  268 /**
  269  * gtk_databox_xyyc_graph_get_X:
  270  * @xyyc_graph: A #GtkDataboxXYYCGraph object
  271  *
  272  * Gets the X values of the @xzc_graph.
  273  *
  274  * Return value: Pointer to X values
  275  */
  276 gfloat *
  277 gtk_databox_xyyc_graph_get_X (GtkDataboxXYYCGraph * xyyc_graph)
  278 {
  279    g_return_val_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph), NULL);
  280    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  281    return priv->X;
  282 }
  283 
  284 /**
  285  * gtk_databox_xyyc_graph_get_Y1:
  286  * @xyyc_graph: A #GtkDataboxXYYCGraph object
  287  *
  288  * Gets the Y1 values of the @xzc_graph.
  289  *
  290  * Return value: Pointer to Y1 values
  291  */
  292 gfloat *
  293 gtk_databox_xyyc_graph_get_Y1 (GtkDataboxXYYCGraph * xyyc_graph)
  294 {
  295    g_return_val_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph), NULL);
  296    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  297    return priv->Y1;
  298 }
  299 
  300 /**
  301  * gtk_databox_xyyc_graph_get_Y2:
  302  * @xyyc_graph: A #GtkDataboxXYYCGraph object
  303  *
  304  * Gets the Y2 values of the @xzc_graph.
  305  *
  306  * Return value: Pointer to Y2 values
  307  */
  308 gfloat *
  309 gtk_databox_xyyc_graph_get_Y2 (GtkDataboxXYYCGraph * xyyc_graph)
  310 {
  311    g_return_val_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph), NULL);
  312    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  313    return priv->Y2;
  314 }
  315 
  316 /**
  317  * gtk_databox_xyyc_graph_get_length:
  318  * @xyyc_graph: A #GtkDataboxXYYCGraph object
  319  *
  320  * Gets the the length of the X and Y values arrays.
  321  *
  322  * Return value: Length of X/Y arrays.
  323  */
  324 guint
  325 gtk_databox_xyyc_graph_get_length (GtkDataboxXYYCGraph * xyyc_graph)
  326 {
  327    g_return_val_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph), 0);
  328    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  329    return priv->len;
  330 }
  331 
  332 /**
  333  * gtk_databox_xyyc_graph_get_maxlen:
  334  * @xyyc_graph: A #GtkDataboxXYYCGraph object
  335  *
  336  * Gets the the maxlen of the X and Y values arrays.
  337  *
  338  * Return value: Size of X/Y arrays (size of the allocated storage).
  339  */
  340 guint
  341 gtk_databox_xyyc_graph_get_maxlen (GtkDataboxXYYCGraph * xyyc_graph)
  342 {
  343    g_return_val_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph), 0);
  344    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  345    return priv->maxlen;
  346 }
  347 
  348 /**
  349  * gtk_databox_xyyc_graph_get_xstart:
  350  * @xyyc_graph: A #GtkDataboxXYYCGraph object
  351  *
  352  * Gets the the start offset of the X values array.  This is the element in the array pointed to by X that will be the first element plotted.
  353  * If X is a pointer to a gfloat array, and xstart is 5, then x[5] will be the first data element.  If Xstride is 1, then x[6] will be the
  354  * second element.  x[5 + len - 1] will be last element.
  355  * Usually, xstart will be 0.  It can be nonzero to allow for interleaved X/Y samples, or if the data is stored as a matrix, then X can point
  356  * to the start of the matrix, xstart can be the column number, and xstride the number of columns.
  357  *
  358  * Return value: The xstart value.
  359  */
  360 guint
  361 gtk_databox_xyyc_graph_get_xstart (GtkDataboxXYYCGraph * xyyc_graph)
  362 {
  363    g_return_val_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph), 0);
  364    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  365    return priv->xstart;
  366 }
  367 
  368 /**
  369  * gtk_databox_xyyc_graph_get_y1start:
  370  * @xyyc_graph: A #GtkDataboxXYYCGraph object
  371  *
  372  * Gets the the start offset of the Y1 values array.  This is the element in the array pointed to by Y that will be the first element plotted.
  373  * If Y1 is a pointer to a gfloat array, and y1start is 5, then y1[5] will be the first data element.  If y1stride is 1, then y1[6] will be the
  374  * second element.  y1[5 + len - 1] will be last element.
  375  * Usually, y1start will be 0.  It can be nonzero to allow for interleaved X/Y1/Y2 samples, or if the data is stored as a matrix, then Y1 can point
  376  * to the start of the matrix, y1start can be the column number, and y1stride the number of columns.
  377  *
  378  * Return value: The y1start value.
  379  */
  380 guint
  381 gtk_databox_xyyc_graph_get_y1start (GtkDataboxXYYCGraph * xyyc_graph)
  382 {
  383    g_return_val_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph), 0);
  384    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  385    return priv->y1start;
  386 }
  387 
  388 /**
  389  * gtk_databox_xyyc_graph_get_y2start:
  390  * @xyyc_graph: A #GtkDataboxXYYCGraph object
  391  *
  392  * Gets the the start offset of the Y2 values array.  This is the element in the array pointed to by Y that will be the first element plotted.
  393  * If Y2 is a pointer to a gfloat array, and y2start is 5, then y2[5] will be the first data element.  If y2stride is 1, then y2[6] will be the
  394  * second element.  y2[5 + len - 1] will be last element.
  395  * Usually, y2start will be 0.  It can be nonzero to allow for interleaved X/Y1/Y2 samples, or if the data is stored as a matrix, then Y2 can point
  396  * to the start of the matrix, y2start can be the column number, and y2stride the number of columns.
  397  *
  398  * Return value: The y2start value.
  399  */
  400 guint
  401 gtk_databox_xyyc_graph_get_y2start (GtkDataboxXYYCGraph * xyyc_graph)
  402 {
  403    g_return_val_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph), 0);
  404    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  405    return priv->y2start;
  406 }
  407 
  408 /**
  409  * gtk_databox_xyyc_graph_get_xstride:
  410  * @xyyc_graph: A #GtkDataboxXYYCGraph object
  411  *
  412  * Gets the the stride offset of the X values array.  This is the element in the array pointed to by X that will be the first element plotted.
  413  * If X is a pointer to a gfloat array, and xstart is 5, then x[5] will be the first data element.  If Xstride is 1, then x[6] will be the
  414  * second element.  x[5 + len - 1] will be last element.
  415  * Usually, xstride will be 1.  It can be nonzero to allow for interleaved X/Y samples, or if the data is stored as a matrix, then X can point
  416  * to the start of the matrix, xstart can be the column number, and xstride the number of columns.
  417  *
  418  * Return value: The xstride value.
  419  */
  420 guint
  421 gtk_databox_xyyc_graph_get_xstride (GtkDataboxXYYCGraph * xyyc_graph)
  422 {
  423    g_return_val_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph), 0);
  424    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  425    return priv->xstride;
  426 }
  427 
  428 /**
  429  * gtk_databox_xyyc_graph_get_y1stride:
  430  * @xyyc_graph: A #GtkDataboxXYYCGraph object
  431  *
  432  * Gets the the stride offset of the Y1 values array.  This is the element in the array pointed to by Y1 that will be the first element plotted.
  433  * If Y1 is a pointer to a gfloat array, and y1start is 5, then y1[5] will be the first data element.  If y1stride is 1, then y1[6] will be the
  434  * second element.  y1[5 + len - 1] will be last element.
  435  * Usually, y1stride will be 1.  It can be nonzero to allow for interleaved X/Y1/Y2 samples, or if the data is stored as a matrix, then Y1 can point
  436  * to the start of the matrix, y1start can be the column number, and y1stride the number of columns.
  437  *
  438  * Return value: The y1stride value.
  439  */
  440 guint
  441 gtk_databox_xyyc_graph_get_y1stride (GtkDataboxXYYCGraph * xyyc_graph)
  442 {
  443    g_return_val_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph), 0);
  444    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  445    return priv->y1stride;
  446 }
  447 
  448 /**
  449  * gtk_databox_xyyc_graph_get_y2stride:
  450  * @xyyc_graph: A #GtkDataboxXYYCGraph object
  451  *
  452  * Gets the the stride offset of the Y2 values array.  This is the element in the array pointed to by Y2 that will be the first element plotted.
  453  * If Y2 is a pointer to a gfloat array, and y2start is 5, then y2[5] will be the first data element.  If y2stride is 1, then y2[6] will be the
  454  * second element.  y2[5 + len - 1] will be last element.
  455  * Usually, y2stride will be 1.  It can be nonzero to allow for interleaved X/Y1/Y2 samples, or if the data is stored as a matrix, then Y2 can point
  456  * to the start of the matrix, y2start can be the column number, and y2stride the number of columns.
  457  *
  458  * Return value: The y2stride value.
  459  */
  460 guint
  461 gtk_databox_xyyc_graph_get_y2stride (GtkDataboxXYYCGraph * xyyc_graph)
  462 {
  463    g_return_val_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph), 0);
  464    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  465    return priv->y2stride;
  466 }
  467 
  468 /**
  469  * gtk_databox_xyyc_graph_get_xtype:
  470  * @xyyc_graph: A #GtkDataboxXYYCGraph object
  471  *
  472  * Gets the the GType of the X array elements.  This may be G_TYPE_FLOAT, G_TYPE_DOUBLE, or similar.
  473  *
  474  * Return value: A GType, usually this is G_TYPE_FLOAT.
  475  */
  476 GType
  477 gtk_databox_xyyc_graph_get_xtype (GtkDataboxXYYCGraph * xyyc_graph)
  478 {
  479    g_return_val_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph), 0);
  480    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  481    return priv->xtype;
  482 }
  483 
  484 /**
  485  * gtk_databox_xyyc_graph_get_ytype:
  486  * @xyyc_graph: A #GtkDataboxXYYCGraph object
  487  *
  488  * Gets the the GType of the Y1/Y2 array elements.  This may be G_TYPE_FLOAT, G_TYPE_DOUBLE, or similar.
  489  *
  490  * Return value: A GType, usually this is G_TYPE_FLOAT.
  491  */
  492 GType
  493 gtk_databox_xyyc_graph_get_ytype (GtkDataboxXYYCGraph * xyyc_graph)
  494 {
  495    g_return_val_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph), 0);
  496    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  497    return priv->ytype;
  498 }
  499 
  500 static void
  501 gtk_databox_xyyc_graph_get_property (GObject * object,
  502                     guint property_id,
  503                     GValue * value, GParamSpec * pspec)
  504 {
  505    GtkDataboxXYYCGraph *xyyc_graph = GTK_DATABOX_XYYC_GRAPH (object);
  506 
  507    switch (property_id)
  508    {
  509    case PROP_X:
  510       g_value_set_pointer (value, gtk_databox_xyyc_graph_get_X (xyyc_graph));
  511       break;
  512    case PROP_Y1:
  513       g_value_set_pointer (value, gtk_databox_xyyc_graph_get_Y1 (xyyc_graph));
  514       break;
  515    case PROP_Y2:
  516       g_value_set_pointer (value, gtk_databox_xyyc_graph_get_Y2 (xyyc_graph));
  517       break;
  518    case PROP_LEN:
  519       g_value_set_int (value, gtk_databox_xyyc_graph_get_length (xyyc_graph));
  520       break;
  521    case PROP_SIZE:
  522       g_value_set_int (value, gtk_databox_xyyc_graph_get_maxlen (xyyc_graph));
  523       break;
  524    case PROP_XSTART:
  525       g_value_set_int (value, gtk_databox_xyyc_graph_get_xstart (xyyc_graph));
  526       break;
  527    case PROP_Y1START:
  528       g_value_set_int (value, gtk_databox_xyyc_graph_get_y1start (xyyc_graph));
  529       break;
  530    case PROP_Y2START:
  531       g_value_set_int (value, gtk_databox_xyyc_graph_get_y2start (xyyc_graph));
  532       break;
  533    case PROP_XSTRIDE:
  534       g_value_set_int (value, gtk_databox_xyyc_graph_get_xstride (xyyc_graph));
  535       break;
  536    case PROP_Y1STRIDE:
  537       g_value_set_int (value, gtk_databox_xyyc_graph_get_y1stride (xyyc_graph));
  538       break;
  539    case PROP_Y2STRIDE:
  540       g_value_set_int (value, gtk_databox_xyyc_graph_get_y2stride (xyyc_graph));
  541       break;
  542    case PROP_XTYPE:
  543       g_value_set_gtype (value, gtk_databox_xyyc_graph_get_xtype (xyyc_graph));
  544       break;
  545    case PROP_YTYPE:
  546       g_value_set_gtype (value, gtk_databox_xyyc_graph_get_ytype (xyyc_graph));
  547       break;
  548    default:
  549       /* We don't have any other property... */
  550       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  551       break;
  552    }
  553 }
  554 
  555 static void
  556 gtk_databox_xyyc_graph_class_init (GtkDataboxXYYCGraphClass *klass)
  557 {
  558    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  559    GtkDataboxGraphClass *graph_class = GTK_DATABOX_GRAPH_CLASS (klass);
  560    GParamSpec *xyyc_graph_param_spec;
  561 
  562    gobject_class->set_property = gtk_databox_xyyc_graph_set_property;
  563    gobject_class->get_property = gtk_databox_xyyc_graph_get_property;
  564 
  565    xyyc_graph_param_spec = g_param_spec_pointer ("X-Values",
  566                         "X coordinates",
  567                         "X values of data",
  568                         G_PARAM_CONSTRUCT_ONLY |
  569                         G_PARAM_READWRITE);
  570 
  571    g_object_class_install_property (gobject_class,
  572                     PROP_X, xyyc_graph_param_spec);
  573 
  574    xyyc_graph_param_spec = g_param_spec_pointer ("Y1-Values",
  575                         "Y1 coordinates",
  576                         "Y1 values of data",
  577                         G_PARAM_CONSTRUCT_ONLY |
  578                         G_PARAM_READWRITE);
  579 
  580    g_object_class_install_property (gobject_class,
  581                     PROP_Y1, xyyc_graph_param_spec);
  582 
  583    xyyc_graph_param_spec = g_param_spec_pointer ("Y2-Values",
  584                         "Y2 coordinates",
  585                         "Y2 values of data",
  586                         G_PARAM_CONSTRUCT_ONLY |
  587                         G_PARAM_READWRITE);
  588 
  589    g_object_class_install_property (gobject_class,
  590                     PROP_Y2, xyyc_graph_param_spec);
  591 
  592    xyyc_graph_param_spec = g_param_spec_int ("length", "length of X, Y1 and Y2", "number of data points", G_MININT, G_MAXINT, 0,    /* default value */
  593                         G_PARAM_CONSTRUCT_ONLY |
  594                         G_PARAM_READWRITE);
  595 
  596    g_object_class_install_property (gobject_class,
  597                     PROP_LEN, xyyc_graph_param_spec);
  598 
  599    xyyc_graph_param_spec = g_param_spec_int ("maxlen", "maxlen of X and Y", "maximal number of data points", G_MININT, G_MAXINT, 0, /* default value */
  600                         G_PARAM_CONSTRUCT_ONLY |
  601                         G_PARAM_READWRITE);
  602    g_object_class_install_property (gobject_class,
  603                     PROP_SIZE, xyyc_graph_param_spec);
  604 
  605    xyyc_graph_param_spec = g_param_spec_int ("xstart", "array index of first X", "array index of first X", G_MININT, G_MAXINT, 0,   /* default value */
  606                         G_PARAM_CONSTRUCT_ONLY |
  607                         G_PARAM_READWRITE);
  608    g_object_class_install_property (gobject_class,
  609                     PROP_XSTART, xyyc_graph_param_spec);
  610 
  611    xyyc_graph_param_spec = g_param_spec_int ("y1start", "array index of first Y1", "array index of first Y1", G_MININT, G_MAXINT, 0,    /* default value */
  612                         G_PARAM_CONSTRUCT_ONLY |
  613                         G_PARAM_READWRITE);
  614    g_object_class_install_property (gobject_class,
  615                     PROP_Y1START, xyyc_graph_param_spec);
  616 
  617    xyyc_graph_param_spec = g_param_spec_int ("y2start", "array index of first Y2", "array index of first Y2", G_MININT, G_MAXINT, 0,    /* default value */
  618                         G_PARAM_CONSTRUCT_ONLY |
  619                         G_PARAM_READWRITE);
  620    g_object_class_install_property (gobject_class,
  621                     PROP_Y2START, xyyc_graph_param_spec);
  622 
  623    xyyc_graph_param_spec = g_param_spec_int ("xstride", "stride of X values", "stride of X values", G_MININT, G_MAXINT, 1,  /* default value */
  624                         G_PARAM_CONSTRUCT_ONLY |
  625                         G_PARAM_READWRITE);
  626    g_object_class_install_property (gobject_class,
  627                     PROP_XSTRIDE, xyyc_graph_param_spec);
  628 
  629    xyyc_graph_param_spec = g_param_spec_int ("y1stride", "stride of Y1 values", "stride of Y1 values", G_MININT, G_MAXINT, 1,   /* default value */
  630                         G_PARAM_CONSTRUCT_ONLY |
  631                         G_PARAM_READWRITE);
  632    g_object_class_install_property (gobject_class,
  633                     PROP_Y1STRIDE, xyyc_graph_param_spec);
  634 
  635    xyyc_graph_param_spec = g_param_spec_int ("y2stride", "stride of Y2 values", "stride of Y2 values", G_MININT, G_MAXINT, 1,   /* default value */
  636                         G_PARAM_CONSTRUCT_ONLY |
  637                         G_PARAM_READWRITE);
  638    g_object_class_install_property (gobject_class,
  639                     PROP_Y2STRIDE, xyyc_graph_param_spec);
  640 
  641    xyyc_graph_param_spec = g_param_spec_gtype ("xtype", "GType of X elements", "GType of X elements", G_TYPE_NONE,
  642                         G_PARAM_CONSTRUCT_ONLY |
  643                         G_PARAM_READWRITE);
  644    g_object_class_install_property (gobject_class,
  645                     PROP_XTYPE, xyyc_graph_param_spec);
  646 
  647    xyyc_graph_param_spec = g_param_spec_gtype ("ytype", "GType of Y1/Y2 elements", "GType of Y1/Y2 elements", G_TYPE_NONE,
  648                         G_PARAM_CONSTRUCT_ONLY |
  649                         G_PARAM_READWRITE);
  650    g_object_class_install_property (gobject_class,
  651                     PROP_YTYPE, xyyc_graph_param_spec);
  652 
  653    graph_class->calculate_extrema =
  654       gtk_databox_xyyc_graph_real_calculate_extrema;
  655 }
  656 
  657 static void
  658 gtk_databox_xyyc_graph_init (GtkDataboxXYYCGraph * xyyc_graph)
  659 {
  660    if (xyyc_graph == NULL) g_warning ("xyyc_graph_init with NULL");
  661 }
  662 
  663 static gint
  664 gtk_databox_xyyc_graph_real_calculate_extrema (GtkDataboxGraph * graph,
  665                           gfloat * min_x, gfloat * max_x,
  666                           gfloat * min_y, gfloat * max_y)
  667 {
  668    GtkDataboxXYYCGraph *xyyc_graph = GTK_DATABOX_XYYC_GRAPH (graph);
  669    GtkDataboxXYYCGraphPrivate *priv = gtk_databox_xyyc_graph_get_instance_private (xyyc_graph);
  670    guint i, indx, len, maxlen, start, stride;
  671    void *values;
  672    GType vtype;
  673    gfloat fval = 0.0, minval = 0.0, maxval = 0.0;
  674 
  675    g_return_val_if_fail (GTK_DATABOX_IS_XYYC_GRAPH (xyyc_graph), -1);
  676    g_return_val_if_fail (min_x, -1);
  677    g_return_val_if_fail (max_x, -1);
  678    g_return_val_if_fail (min_y, -1);
  679    g_return_val_if_fail (max_y, -1);
  680    g_return_val_if_fail (priv->len, -1);
  681 
  682    len = priv->len;
  683    maxlen = priv->maxlen;
  684    values = priv->X;
  685    vtype = priv->xtype;
  686    start = priv->xstart;
  687    stride = priv->xstride;
  688 
  689    indx = start * stride;
  690    i = 0;
  691    do {
  692         if (vtype == G_TYPE_FLOAT)
  693             fval = ((gfloat *)values)[indx];
  694         else if (vtype == G_TYPE_DOUBLE)
  695             fval = ((gdouble *)values)[indx];
  696         else if (vtype == G_TYPE_INT)
  697             fval = ((gint *)values)[indx];
  698         else if (vtype == G_TYPE_UINT)
  699             fval = ((guint *)values)[indx];
  700         else if (vtype == G_TYPE_LONG)
  701             fval = ((glong *)values)[indx];
  702         else if (vtype == G_TYPE_ULONG)
  703             fval = ((gulong *)values)[indx];
  704         else if (vtype == G_TYPE_INT64)
  705             fval = ((gint64 *)values)[indx];
  706         else if (vtype == G_TYPE_UINT64)
  707             fval = ((guint64 *)values)[indx];
  708         else if (vtype == G_TYPE_CHAR)
  709             fval = ((gchar *)values)[indx];
  710         else if (vtype == G_TYPE_UCHAR)
  711             fval = ((guchar *)values)[indx];
  712 
  713         if (i==0)
  714         {
  715             minval = maxval = fval;
  716         }
  717         else
  718         {
  719             if (fval < minval) minval = fval;
  720             if (fval > maxval) maxval = fval;
  721         }
  722 
  723         /* handle the wrap-around (ring buffer) issue using modulus.  for efficiency, don't do this for non-wraparound cases. */
  724         /* note this allows multiple wrap-arounds.  One could hold a single cycle of a sine wave, and plot a continuous wave */
  725         /* This can be optimized using pointers later */
  726         if (i + start > maxlen)
  727             indx = ((i + start) % maxlen) * stride;
  728         else
  729             indx += stride;
  730    } while (++i < len);
  731 
  732    *min_x = minval;
  733    *max_x = maxval;
  734 
  735    values = priv->Y1;
  736    vtype = priv->ytype;
  737    start = priv->y1start;
  738    stride = priv->y1stride;
  739 
  740    indx = start * stride;
  741    i = 0;
  742    do {
  743         if (vtype == G_TYPE_FLOAT)
  744             fval = ((gfloat *)values)[indx];
  745         else if (vtype == G_TYPE_DOUBLE)
  746             fval = ((gdouble *)values)[indx];
  747         else if (vtype == G_TYPE_INT)
  748             fval = ((gint *)values)[indx];
  749         else if (vtype == G_TYPE_UINT)
  750             fval = ((guint *)values)[indx];
  751         else if (vtype == G_TYPE_LONG)
  752             fval = ((glong *)values)[indx];
  753         else if (vtype == G_TYPE_ULONG)
  754             fval = ((gulong *)values)[indx];
  755         else if (vtype == G_TYPE_INT64)
  756             fval = ((gint64 *)values)[indx];
  757         else if (vtype == G_TYPE_UINT64)
  758             fval = ((guint64 *)values)[indx];
  759         else if (vtype == G_TYPE_CHAR)
  760             fval = ((gchar *)values)[indx];
  761         else if (vtype == G_TYPE_UCHAR)
  762             fval = ((guchar *)values)[indx];
  763 
  764         if (i==0) /* yes putting this check inside the loop is inefficient, but it makes the code simpler */
  765         {
  766             minval = maxval = fval;
  767         }
  768         else
  769         {
  770             if (fval < minval) minval = fval;
  771             if (fval > maxval) maxval = fval;
  772         }
  773 
  774         /* handle the wrap-around (ring buffer) issue using modulus.  for efficiency, don't do this for non-wraparound cases. */
  775         /* note this allows multiple wrap-arounds.  One could hold a single cycle of a sine wave, and plot a continuous wave */
  776         /* This can be optimized using pointers later */
  777         if (i + start > maxlen)
  778             indx = ((i + start) % maxlen) * stride;
  779         else
  780             indx += stride;
  781    } while (++i < len);
  782 
  783    values = priv->Y2;
  784    start = priv->y2start;
  785    stride = priv->y2stride;
  786 
  787    indx = start * stride;
  788    i = 0;
  789    do {
  790         if (vtype == G_TYPE_FLOAT)
  791             fval = ((gfloat *)values)[indx];
  792         else if (vtype == G_TYPE_DOUBLE)
  793             fval = ((gdouble *)values)[indx];
  794         else if (vtype == G_TYPE_INT)
  795             fval = ((gint *)values)[indx];
  796         else if (vtype == G_TYPE_UINT)
  797             fval = ((guint *)values)[indx];
  798         else if (vtype == G_TYPE_LONG)
  799             fval = ((glong *)values)[indx];
  800         else if (vtype == G_TYPE_ULONG)
  801             fval = ((gulong *)values)[indx];
  802         else if (vtype == G_TYPE_INT64)
  803             fval = ((gint64 *)values)[indx];
  804         else if (vtype == G_TYPE_UINT64)
  805             fval = ((guint64 *)values)[indx];
  806         else if (vtype == G_TYPE_CHAR)
  807             fval = ((gchar *)values)[indx];
  808         else if (vtype == G_TYPE_UCHAR)
  809             fval = ((guchar *)values)[indx];
  810 
  811         /* Note that this is different from where we checked Y1 */
  812         if (fval < minval) minval = fval;
  813         if (fval > maxval) maxval = fval;
  814 
  815         /* handle the wrap-around (ring buffer) issue using modulus.  for efficiency, don't do this for non-wraparound cases. */
  816         /* note this allows multiple wrap-arounds.  One could hold a single cycle of a sine wave, and plot a continuous wave */
  817         /* This can be optimized using pointers later */
  818         if (i + start > maxlen)
  819             indx = ((i + start) % maxlen) * stride;
  820         else
  821             indx += stride;
  822    } while (++i < len);
  823 
  824    *min_y = minval;
  825    *max_y = maxval;
  826 
  827    return 0;
  828 }