"Fossies" - the Fresh Open Source Software Archive

Member "gtkdatabox-1.0.0/gtk/gtkdatabox_xyc_graph.c" (31 Mar 2021, 22495 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_xyc_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_xyc_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  *
    5  * This program is free software; you can redistribute it and/or
    6  * modify it under the terms of the GNU Lesser General Public License
    7  * as published by the Free Software Foundation; either version 2.1
    8  * of the License, or (at your option) any later version.
    9  *
   10  * This program is distributed in the hope that it will be useful,
   11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13  * GNU Lesser General Public License for more details.
   14  *
   15  * You should have received a copy of the GNU General Public License
   16  * along with this program; if not, write to the Free Software
   17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   18  */
   19 
   20 #include <gtkdatabox_xyc_graph.h>
   21 
   22 static gint gtk_databox_xyc_graph_real_calculate_extrema (GtkDataboxGraph *
   23                               xyc_graph,
   24                               gfloat * min_x,
   25                               gfloat * max_x,
   26                               gfloat * min_y,
   27                               gfloat * max_y);
   28 
   29 /* IDs of properties */
   30 enum
   31 {
   32    PROP_X = 1,
   33    PROP_Y,
   34    PROP_LEN,
   35    PROP_MAXLEN,
   36    PROP_XSTART,
   37    PROP_YSTART,
   38    PROP_XSTRIDE,
   39    PROP_YSTRIDE,
   40    PROP_XTYPE,
   41    PROP_YTYPE
   42 };
   43 
   44 /**
   45  * GtkDataboxXYCGraphPrivate
   46  *
   47  * A private data structure used by the #GtkDataboxXYCGraph. It shields all internal things
   48  * from developers who are just using the object.
   49  *
   50  **/
   51 typedef struct _GtkDataboxXYCGraphPrivate GtkDataboxXYCGraphPrivate;
   52 
   53 struct _GtkDataboxXYCGraphPrivate
   54 {
   55    gfloat *X;
   56    gfloat *Y;
   57    guint len;
   58    guint maxlen;
   59    guint xstart;
   60    guint ystart;
   61    guint xstride;
   62    guint ystride;
   63    GType xtype;
   64    GType ytype;
   65 };
   66 
   67 G_DEFINE_TYPE_WITH_PRIVATE(GtkDataboxXYCGraph, gtk_databox_xyc_graph,
   68     GTK_DATABOX_TYPE_GRAPH)
   69 
   70 //static gpointer parent_class = NULL;
   71 
   72 void
   73 gtk_databox_xyc_graph_set_X_Y_length(GtkDataboxXYCGraph * xyc_graph, gfloat * X, gfloat * Y, guint len)
   74 {
   75    g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
   76    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
   77    priv->X = X;
   78    priv->Y = Y;
   79    priv->len = len;
   80 }
   81 
   82 static void
   83 gtk_databox_xyc_graph_set_X (GtkDataboxXYCGraph * xyc_graph, gfloat * X)
   84 {
   85    g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
   86    g_return_if_fail (X);
   87    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
   88    priv->X = X;
   89 
   90    g_object_notify (G_OBJECT (xyc_graph), "X-Values");
   91 }
   92 
   93 static void
   94 gtk_databox_xyc_graph_set_Y (GtkDataboxXYCGraph * xyc_graph, gfloat * Y)
   95 {
   96    g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
   97    g_return_if_fail (Y);
   98    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
   99    priv->Y = Y;
  100 
  101    g_object_notify (G_OBJECT (xyc_graph), "Y-Values");
  102 }
  103 
  104 static void
  105 gtk_databox_xyc_graph_set_length (GtkDataboxXYCGraph * xyc_graph, guint len)
  106 {
  107    g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
  108    g_return_if_fail (len > 0);
  109    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  110    priv->len = len;
  111 
  112    g_object_notify (G_OBJECT (xyc_graph), "length");
  113 }
  114 
  115 static void
  116 gtk_databox_xyc_graph_set_maxlen (GtkDataboxXYCGraph * xyc_graph, guint maxlen)
  117 {
  118    g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
  119    g_return_if_fail (maxlen > 0);
  120    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  121    priv->maxlen = maxlen;
  122 
  123    g_object_notify (G_OBJECT (xyc_graph), "maxlen");
  124 }
  125 
  126 static void
  127 gtk_databox_xyc_graph_set_xstart (GtkDataboxXYCGraph * xyc_graph, guint xstart)
  128 {
  129    g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
  130    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  131    priv->xstart = xstart;
  132 
  133    g_object_notify (G_OBJECT (xyc_graph), "X-Values");
  134 }
  135 
  136 static void
  137 gtk_databox_xyc_graph_set_ystart (GtkDataboxXYCGraph * xyc_graph, guint ystart)
  138 {
  139    g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
  140    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  141    priv->ystart = ystart;
  142 
  143    g_object_notify (G_OBJECT (xyc_graph), "Y-Values");
  144 }
  145 
  146 static void
  147 gtk_databox_xyc_graph_set_xstride (GtkDataboxXYCGraph * xyc_graph, guint xstride)
  148 {
  149    g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
  150    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  151    priv->xstride = xstride;
  152 
  153    g_object_notify (G_OBJECT (xyc_graph), "X-Values");
  154 }
  155 
  156 static void
  157 gtk_databox_xyc_graph_set_ystride (GtkDataboxXYCGraph * xyc_graph, guint ystride)
  158 {
  159    g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
  160    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  161    priv->ystride = ystride;
  162 
  163    g_object_notify (G_OBJECT (xyc_graph), "Y-Values");
  164 }
  165 
  166 static void
  167 gtk_databox_xyc_graph_set_xtype (GtkDataboxXYCGraph * xyc_graph, GType xtype)
  168 {
  169    g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
  170    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  171    priv->xtype = xtype;
  172 
  173    g_object_notify (G_OBJECT (xyc_graph), "X-Values");
  174 }
  175 
  176 static void
  177 gtk_databox_xyc_graph_set_ytype (GtkDataboxXYCGraph * xyc_graph, GType ytype)
  178 {
  179    g_return_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph));
  180 
  181    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  182    priv->ytype = ytype;
  183 
  184    g_object_notify (G_OBJECT (xyc_graph), "Y-Values");
  185 }
  186 
  187 static void
  188 gtk_databox_xyc_graph_set_property (GObject * object,
  189                     guint property_id,
  190                     const GValue * value, GParamSpec * pspec)
  191 {
  192    GtkDataboxXYCGraph *xyc_graph = GTK_DATABOX_XYC_GRAPH (object);
  193 
  194    switch (property_id)
  195    {
  196    case PROP_X:
  197       gtk_databox_xyc_graph_set_X (xyc_graph, (gfloat *) g_value_get_pointer (value));
  198       break;
  199    case PROP_Y:
  200       gtk_databox_xyc_graph_set_Y (xyc_graph, (gfloat *) g_value_get_pointer (value));
  201       break;
  202    case PROP_LEN:
  203       gtk_databox_xyc_graph_set_length (xyc_graph, g_value_get_int (value));
  204       break;
  205    case PROP_MAXLEN:
  206       gtk_databox_xyc_graph_set_maxlen (xyc_graph, g_value_get_int (value));
  207       break;
  208    case PROP_XSTART:
  209       gtk_databox_xyc_graph_set_xstart (xyc_graph, g_value_get_int (value));
  210       break;
  211    case PROP_YSTART:
  212       gtk_databox_xyc_graph_set_ystart (xyc_graph, g_value_get_int (value));
  213       break;
  214    case PROP_XSTRIDE:
  215       gtk_databox_xyc_graph_set_xstride (xyc_graph, g_value_get_int (value));
  216       break;
  217    case PROP_YSTRIDE:
  218       gtk_databox_xyc_graph_set_ystride (xyc_graph, g_value_get_int (value));
  219       break;
  220    case PROP_XTYPE:
  221       gtk_databox_xyc_graph_set_xtype (xyc_graph, g_value_get_gtype (value));
  222       break;
  223    case PROP_YTYPE:
  224       gtk_databox_xyc_graph_set_ytype (xyc_graph, g_value_get_gtype (value));
  225       break;
  226    default:
  227       /* We don't have any other property... */
  228       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  229       break;
  230    }
  231 }
  232 
  233 /**
  234  * gtk_databox_xyc_graph_get_X:
  235  * @xyc_graph: A #GtkDataboxXYCGraph object
  236  *
  237  * Gets the X values of the @xzc_graph.
  238  *
  239  * Return value: Pointer to X values
  240  */
  241 gfloat *
  242 gtk_databox_xyc_graph_get_X (GtkDataboxXYCGraph * xyc_graph)
  243 {
  244    g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), NULL);
  245    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  246    return priv->X;
  247 }
  248 
  249 /**
  250  * gtk_databox_xyc_graph_get_Y:
  251  * @xyc_graph: A #GtkDataboxXYCGraph object
  252  *
  253  * Gets the Y values of the @xzc_graph.
  254  *
  255  * Return value: Pointer to Y values
  256  */
  257 gfloat *
  258 gtk_databox_xyc_graph_get_Y (GtkDataboxXYCGraph * xyc_graph)
  259 {
  260    g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), NULL);
  261    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  262    return priv->Y;
  263 }
  264 
  265 /**
  266  * gtk_databox_xyc_graph_get_length:
  267  * @xyc_graph: A #GtkDataboxXYCGraph object
  268  *
  269  * Gets the the length of the X and Y values arrays.
  270  *
  271  * Return value: Length of X/Y arrays.
  272  */
  273 guint
  274 gtk_databox_xyc_graph_get_length (GtkDataboxXYCGraph * xyc_graph)
  275 {
  276    g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), 0);
  277    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  278    return priv->len;
  279 }
  280 
  281 /**
  282  * gtk_databox_xyc_graph_get_maxlen:
  283  * @xyc_graph: A #GtkDataboxXYCGraph object
  284  *
  285  * Gets the the maxlen of the X and Y values arrays.
  286  *
  287  * Return value: Size of X/Y arrays.
  288  */
  289 guint
  290 gtk_databox_xyc_graph_get_maxlen (GtkDataboxXYCGraph * xyc_graph)
  291 {
  292    g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), 0);
  293    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  294    return priv->maxlen;
  295 }
  296 
  297 /**
  298  * gtk_databox_xyc_graph_get_xstart:
  299  * @xyc_graph: A #GtkDataboxXYCGraph object
  300  *
  301  * 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.
  302  * 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
  303  * second element.  x[5 + len - 1] will be last element.
  304  * 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
  305  * to the start of the matrix, xstart can be the column number, and xstride the number of columns.
  306  *
  307  * Return value: The xstart value.
  308  */
  309 guint
  310 gtk_databox_xyc_graph_get_xstart (GtkDataboxXYCGraph * xyc_graph)
  311 {
  312    g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), 0);
  313    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  314    return priv->xstart;
  315 }
  316 
  317 /**
  318  * gtk_databox_xyc_graph_get_ystart:
  319  * @xyc_graph: A #GtkDataboxXYCGraph object
  320  *
  321  * Gets the the start offset of the Y values array.  This is the element in the array pointed to by Y that will be the first element plotted.
  322  * If Y is a pointer to a gfloat array, and ystart is 5, then y[5] will be the first data element.  If Ystride is 1, then y[6] will be the
  323  * second element.  y[5 + len - 1] will be last element.
  324  * Usually, ystart will be 0.  It can be nonzero to allow for interleaved X/Y samples, or if the data is stored as a matrix, then Y can point
  325  * to the start of the matrix, ystart can be the column number, and ystride the number of columns.
  326  *
  327  * Return value: The ystart value.
  328  */
  329 guint
  330 gtk_databox_xyc_graph_get_ystart (GtkDataboxXYCGraph * xyc_graph)
  331 {
  332    g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), 0);
  333    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  334    return priv->ystart;
  335 }
  336 
  337 /**
  338  * gtk_databox_xyc_graph_get_xstride:
  339  * @xyc_graph: A #GtkDataboxXYCGraph object
  340  *
  341  * 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.
  342  * 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
  343  * second element.  x[5 + len - 1] will be last element.
  344  * 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
  345  * to the start of the matrix, xstart can be the column number, and xstride the number of columns.
  346  *
  347  * Return value: The xstride value.
  348  */
  349 guint
  350 gtk_databox_xyc_graph_get_xstride (GtkDataboxXYCGraph * xyc_graph)
  351 {
  352    g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), 0);
  353    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  354    return priv->xstride;
  355 }
  356 
  357 /**
  358  * gtk_databox_xyc_graph_get_ystride:
  359  * @xyc_graph: A #GtkDataboxXYCGraph object
  360  *
  361  * Gets the the stride offset of the Y values array.  This is the element in the array pointed to by Y that will be the first element plotted.
  362  * If Y is a pointer to a gfloat array, and ystart is 5, then y[5] will be the first data element.  If Ystride is 1, then y[6] will be the
  363  * second element.  y[5 + len - 1] will be last element.
  364  * Usually, ystride will be 1.  It can be nonzero to allow for interleaved X/Y samples, or if the data is stored as a matrix, then Y can point
  365  * to the start of the matrix, ystart can be the column number, and ystride the number of columns.
  366  *
  367  * Return value: The ystride value.
  368  */
  369 guint
  370 gtk_databox_xyc_graph_get_ystride (GtkDataboxXYCGraph * xyc_graph)
  371 {
  372    g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), 0);
  373    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  374    return priv->ystride;
  375 }
  376 
  377 /**
  378  * gtk_databox_xyc_graph_get_xtype:
  379  * @xyc_graph: A #GtkDataboxXYCGraph object
  380  *
  381  * Gets the the GType of the X array elements.  This may be G_TYPE_FLOAT, G_TYPE_DOUBLE, or similar.
  382  *
  383  * Return value: A GType, usually this is G_TYPE_FLOAT.
  384  */
  385 GType
  386 gtk_databox_xyc_graph_get_xtype (GtkDataboxXYCGraph * xyc_graph)
  387 {
  388    g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), 0);
  389    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  390    return priv->xtype;
  391 }
  392 
  393 /**
  394  * gtk_databox_xyc_graph_get_ytype:
  395  * @xyc_graph: A #GtkDataboxXYCGraph object
  396  *
  397  * Gets the the GType of the Y array elements.  This may be G_TYPE_FLOAT, G_TYPE_DOUBLE, or similar.
  398  *
  399  * Return value: A GType, usually this is G_TYPE_FLOAT.
  400  */
  401 GType
  402 gtk_databox_xyc_graph_get_ytype (GtkDataboxXYCGraph * xyc_graph)
  403 {
  404    g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (xyc_graph), 0);
  405    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  406    return priv->ytype;
  407 }
  408 
  409 static void
  410 gtk_databox_xyc_graph_get_property (GObject * object,
  411                     guint property_id,
  412                     GValue * value, GParamSpec * pspec)
  413 {
  414    GtkDataboxXYCGraph *xyc_graph = GTK_DATABOX_XYC_GRAPH (object);
  415 
  416    switch (property_id)
  417    {
  418    case PROP_X:
  419       g_value_set_pointer (value, gtk_databox_xyc_graph_get_X (xyc_graph));
  420       break;
  421    case PROP_Y:
  422       g_value_set_pointer (value, gtk_databox_xyc_graph_get_Y (xyc_graph));
  423       break;
  424    case PROP_LEN:
  425       g_value_set_int (value, gtk_databox_xyc_graph_get_length (xyc_graph));
  426       break;
  427    case PROP_MAXLEN:
  428       g_value_set_int (value, gtk_databox_xyc_graph_get_maxlen (xyc_graph));
  429       break;
  430    case PROP_XSTART:
  431       g_value_set_int (value, gtk_databox_xyc_graph_get_xstart (xyc_graph));
  432       break;
  433    case PROP_YSTART:
  434       g_value_set_int (value, gtk_databox_xyc_graph_get_ystart (xyc_graph));
  435       break;
  436    case PROP_XSTRIDE:
  437       g_value_set_int (value, gtk_databox_xyc_graph_get_xstride (xyc_graph));
  438       break;
  439    case PROP_YSTRIDE:
  440       g_value_set_int (value, gtk_databox_xyc_graph_get_ystride (xyc_graph));
  441       break;
  442    case PROP_XTYPE:
  443       g_value_set_gtype (value, gtk_databox_xyc_graph_get_xtype (xyc_graph));
  444       break;
  445    case PROP_YTYPE:
  446       g_value_set_gtype (value, gtk_databox_xyc_graph_get_ytype (xyc_graph));
  447       break;
  448    default:
  449       /* We don't have any other property... */
  450       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  451       break;
  452    }
  453 }
  454 
  455 static void
  456 gtk_databox_xyc_graph_class_init (GtkDataboxXYCGraphClass *klass)
  457 {
  458    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  459    GtkDataboxGraphClass *graph_class = GTK_DATABOX_GRAPH_CLASS (klass);
  460    GParamSpec *xyc_graph_param_spec;
  461 
  462    gobject_class->set_property = gtk_databox_xyc_graph_set_property;
  463    gobject_class->get_property = gtk_databox_xyc_graph_get_property;
  464 
  465    xyc_graph_param_spec = g_param_spec_pointer ("X-Values",
  466                         "X coordinates",
  467                         "X values of data",
  468                         G_PARAM_CONSTRUCT_ONLY |
  469                         G_PARAM_READWRITE);
  470 
  471    g_object_class_install_property (gobject_class,
  472                     PROP_X, xyc_graph_param_spec);
  473 
  474    xyc_graph_param_spec = g_param_spec_pointer ("Y-Values",
  475                         "Y coordinates",
  476                         "Y values of data",
  477                         G_PARAM_CONSTRUCT_ONLY |
  478                         G_PARAM_READWRITE);
  479 
  480    g_object_class_install_property (gobject_class,
  481                     PROP_Y, xyc_graph_param_spec);
  482 
  483    xyc_graph_param_spec = g_param_spec_int ("length", "length of X and Y", "number of data points", G_MININT, G_MAXINT, 0,  /* default value */
  484                         G_PARAM_CONSTRUCT_ONLY |
  485                         G_PARAM_READWRITE);
  486 
  487    g_object_class_install_property (gobject_class,
  488                     PROP_LEN, xyc_graph_param_spec);
  489 
  490    xyc_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 */
  491                         G_PARAM_CONSTRUCT_ONLY |
  492                         G_PARAM_READWRITE);
  493    g_object_class_install_property (gobject_class,
  494                     PROP_MAXLEN, xyc_graph_param_spec);
  495 
  496    xyc_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 */
  497                         G_PARAM_CONSTRUCT_ONLY |
  498                         G_PARAM_READWRITE);
  499    g_object_class_install_property (gobject_class,
  500                     PROP_XSTART, xyc_graph_param_spec);
  501 
  502    xyc_graph_param_spec = g_param_spec_int ("ystart", "array index of first Y", "array index of first Y", G_MININT, G_MAXINT, 0,    /* default value */
  503                         G_PARAM_CONSTRUCT_ONLY |
  504                         G_PARAM_READWRITE);
  505    g_object_class_install_property (gobject_class,
  506                     PROP_YSTART, xyc_graph_param_spec);
  507 
  508    xyc_graph_param_spec = g_param_spec_int ("xstride", "stride of X values", "stride of X values", G_MININT, G_MAXINT, 1,   /* default value */
  509                         G_PARAM_CONSTRUCT_ONLY |
  510                         G_PARAM_READWRITE);
  511    g_object_class_install_property (gobject_class,
  512                     PROP_XSTRIDE, xyc_graph_param_spec);
  513 
  514    xyc_graph_param_spec = g_param_spec_int ("ystride", "stride of Y values", "stride of Y values", G_MININT, G_MAXINT, 1,   /* default value */
  515                         G_PARAM_CONSTRUCT_ONLY |
  516                         G_PARAM_READWRITE);
  517    g_object_class_install_property (gobject_class,
  518                     PROP_YSTRIDE, xyc_graph_param_spec);
  519 
  520    xyc_graph_param_spec = g_param_spec_gtype ("xtype", "GType of X elements", "GType of X elements", G_TYPE_NONE,
  521                         G_PARAM_CONSTRUCT_ONLY |
  522                         G_PARAM_READWRITE);
  523    g_object_class_install_property (gobject_class,
  524                     PROP_XTYPE, xyc_graph_param_spec);
  525 
  526    xyc_graph_param_spec = g_param_spec_gtype ("ytype", "GType of Y elements", "GType of Y elements", G_TYPE_NONE,
  527                         G_PARAM_CONSTRUCT_ONLY |
  528                         G_PARAM_READWRITE);
  529    g_object_class_install_property (gobject_class,
  530                     PROP_YTYPE, xyc_graph_param_spec);
  531 
  532    graph_class->calculate_extrema =
  533       gtk_databox_xyc_graph_real_calculate_extrema;
  534 }
  535 
  536 static void
  537 gtk_databox_xyc_graph_init (GtkDataboxXYCGraph *xyc_graph)
  538 {
  539     if (xyc_graph == NULL) g_warning ("xyc_graph_init with NULL");
  540 }
  541 
  542 static gint
  543 gtk_databox_xyc_graph_real_calculate_extrema (GtkDataboxGraph * graph,
  544                           gfloat * min_x, gfloat * max_x,
  545                           gfloat * min_y, gfloat * max_y)
  546 {
  547    GtkDataboxXYCGraph *xyc_graph = GTK_DATABOX_XYC_GRAPH (graph);
  548    GtkDataboxXYCGraphPrivate *priv = gtk_databox_xyc_graph_get_instance_private (xyc_graph);
  549    guint i, indx, len, maxlen, start, stride;
  550    void *values;
  551    GType vtype;
  552    gfloat fval = 0.0, minval = 0.0, maxval = 0.0;
  553 
  554    g_return_val_if_fail (GTK_DATABOX_IS_XYC_GRAPH (graph), -1);
  555    g_return_val_if_fail (min_x, -1);
  556    g_return_val_if_fail (max_x, -1);
  557    g_return_val_if_fail (min_y, -1);
  558    g_return_val_if_fail (max_y, -1);
  559    g_return_val_if_fail (priv->len, -1);
  560 
  561    len = priv->len;
  562    maxlen = priv->maxlen;
  563    values = priv->X;
  564    vtype = priv->xtype;
  565    start = priv->xstart;
  566    stride = priv->xstride;
  567 
  568    indx = start * stride;
  569    i = 0;
  570    do {
  571         if (vtype == G_TYPE_FLOAT)
  572             fval = ((gfloat *)values)[indx];
  573         else if (vtype == G_TYPE_DOUBLE)
  574             fval = ((gdouble *)values)[indx];
  575         else if (vtype == G_TYPE_INT)
  576             fval = ((gint *)values)[indx];
  577         else if (vtype == G_TYPE_UINT)
  578             fval = ((guint *)values)[indx];
  579         else if (vtype == G_TYPE_LONG)
  580             fval = ((glong *)values)[indx];
  581         else if (vtype == G_TYPE_ULONG)
  582             fval = ((gulong *)values)[indx];
  583         else if (vtype == G_TYPE_INT64)
  584             fval = ((gint64 *)values)[indx];
  585         else if (vtype == G_TYPE_UINT64)
  586             fval = ((guint64 *)values)[indx];
  587         else if (vtype == G_TYPE_CHAR)
  588             fval = ((gchar *)values)[indx];
  589         else if (vtype == G_TYPE_UCHAR)
  590             fval = ((guchar *)values)[indx];
  591 
  592         if (i==0)
  593         {
  594             minval = maxval = fval;
  595         }
  596         else
  597         {
  598             if (fval < minval) minval = fval;
  599             if (fval > maxval) maxval = fval;
  600         }
  601 
  602         /* handle the wrap-around (ring buffer) issue using modulus.  for efficiency, don't do this for non-wraparound cases. */
  603         /* note this allows multiple wrap-arounds.  One could hold a single cycle of a sine wave, and plot a continuous wave */
  604         /* This can be optimized using pointers later */
  605         if (i + start > maxlen)
  606             indx = ((i + start) % maxlen) * stride;
  607         else
  608             indx += stride;
  609    } while (++i < len);
  610 
  611    *min_x = minval;
  612    *max_x = maxval;
  613 
  614    values = priv->Y;
  615    vtype = priv->ytype;
  616    start = priv->ystart;
  617    stride = priv->ystride;
  618 
  619    indx = start * stride;
  620    i = 0;
  621    do {
  622         if (vtype == G_TYPE_FLOAT)
  623             fval = ((gfloat *)values)[indx];
  624         else if (vtype == G_TYPE_DOUBLE)
  625             fval = ((gdouble *)values)[indx];
  626         else if (vtype == G_TYPE_INT)
  627             fval = ((gint *)values)[indx];
  628         else if (vtype == G_TYPE_UINT)
  629             fval = ((guint *)values)[indx];
  630         else if (vtype == G_TYPE_LONG)
  631             fval = ((glong *)values)[indx];
  632         else if (vtype == G_TYPE_ULONG)
  633             fval = ((gulong *)values)[indx];
  634         else if (vtype == G_TYPE_INT64)
  635             fval = ((gint64 *)values)[indx];
  636         else if (vtype == G_TYPE_UINT64)
  637             fval = ((guint64 *)values)[indx];
  638         else if (vtype == G_TYPE_CHAR)
  639             fval = ((gchar *)values)[indx];
  640         else if (vtype == G_TYPE_UCHAR)
  641             fval = ((guchar *)values)[indx];
  642 
  643         if (i==0) /* yes putting this check inside the loop is inefficient, but it makes the code simpler */
  644         {
  645             minval = maxval = fval;
  646         }
  647         else
  648         {
  649             if (fval < minval) minval = fval;
  650             if (fval > maxval) maxval = fval;
  651         }
  652 
  653         /* handle the wrap-around (ring buffer) issue using modulus.  for efficiency, don't do this for non-wraparound cases. */
  654         /* note this allows multiple wrap-arounds.  One could hold a single cycle of a sine wave, and plot a continuous wave */
  655         /* This can be optimized using pointers later */
  656         if (i + start > maxlen)
  657             indx = ((i + start) % maxlen) * stride;
  658         else
  659             indx += stride;
  660    } while (++i < len);
  661 
  662    *min_y = minval;
  663    *max_y = maxval;
  664 
  665    return 0;
  666 }