1 /* $Id: gtkdatabox_lines.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_lines.h>
21 
22 G_DEFINE_TYPE(GtkDataboxLines, gtk_databox_lines,
23 	GTK_DATABOX_TYPE_XYC_GRAPH)
24 
25 static void gtk_databox_lines_real_draw (GtkDataboxGraph * lines,
26 					 GtkDatabox* box);
27 
28 /**
29  * GtkDataboxLinesPrivate
30  * @see_also: #GtkDatabox, #GtkDataboxGraph, #GtkDataboxPoints, #GtkDataboxBars, #GtkDataboxMarkers
31  *
32  * A private data structure used by the #GtkDataboxLines. It shields all internal things
33  * from developers who are just using the object.
34  *
35  **/
36 typedef struct _GtkDataboxLinesPrivate GtkDataboxLinesPrivate;
37 
38 struct _GtkDataboxLinesPrivate
39 {
40    gint16 *xpixels;
41    gint16 *ypixels;
42    guint pixelsalloc;
43 };
44 
45 static void
lines_finalize(GObject * object)46 lines_finalize (GObject * object)
47 {
48    GtkDataboxLines *lines = GTK_DATABOX_LINES (object);
49    GtkDataboxLinesPrivate *priv=GTK_DATABOX_LINES_GET_PRIVATE(lines);
50 
51    g_free (priv->xpixels);
52    g_free (priv->ypixels);
53 
54    /* Chain up to the parent class */
55    G_OBJECT_CLASS (gtk_databox_lines_parent_class)->finalize (object);
56 }
57 
58 static void
gtk_databox_lines_class_init(GtkDataboxLinesClass * klass)59 gtk_databox_lines_class_init (GtkDataboxLinesClass *klass)
60 {
61    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
62    GtkDataboxGraphClass *graph_class = GTK_DATABOX_GRAPH_CLASS (klass);
63 
64    gobject_class->finalize = lines_finalize;
65 
66    graph_class->draw = gtk_databox_lines_real_draw;
67 
68    g_type_class_add_private (klass, sizeof (GtkDataboxLinesPrivate));
69 }
70 
71 static void
gtk_databox_lines_init(GtkDataboxLines * lines)72 gtk_databox_lines_init (GtkDataboxLines *lines)
73 {
74    GtkDataboxLinesPrivate *priv=GTK_DATABOX_LINES_GET_PRIVATE(lines);
75    priv->xpixels = NULL;
76    priv->ypixels = NULL;
77    priv->pixelsalloc = 0;
78 }
79 
80 /**
81  * gtk_databox_lines_new:
82  * @len: length of @X and @Y
83  * @X: array of horizontal position values of markers
84  * @Y: array of vertical position values of markers
85  * @color: color of the markers
86  * @size: marker size or line width (depending on the @type)
87  *
88  * Creates a new #GtkDataboxLines object which can be added to a #GtkDatabox widget.
89  *
90  * Return value: A new #GtkDataboxLines object
91  **/
92 GtkDataboxGraph *
gtk_databox_lines_new(guint len,gfloat * X,gfloat * Y,GdkRGBA * color,guint size)93 gtk_databox_lines_new (guint len, gfloat * X, gfloat * Y,
94 		       GdkRGBA * color, guint size)
95 {
96    GtkDataboxLines *lines;
97    g_return_val_if_fail (X, NULL);
98    g_return_val_if_fail (Y, NULL);
99    g_return_val_if_fail ((len > 0), NULL);
100 
101    lines = g_object_new (GTK_DATABOX_TYPE_LINES,
102 			 "X-Values", X,
103 			 "Y-Values", Y,
104 			 "xstart", 0,
105 			 "ystart", 0,
106 			 "xstride", 1,
107 			 "ystride", 1,
108 			 "xtype", G_TYPE_FLOAT,
109 			 "ytype", G_TYPE_FLOAT,
110 			 "length", len,
111 			 "maxlen", len,
112 			 "color", color, "size", size, NULL);
113 
114    return GTK_DATABOX_GRAPH (lines);
115 }
116 
117 /**
118  * gtk_databox_lines_new_full:
119  * @maxlen: maximum length of @X and @Y
120  * @len: actual number of @X and @Y values to plot
121  * @X: array of horizontal position values of markers
122  * @Y: array of vertical position values of markers
123  * @xstart: the first element in the X array to plot (usually 0)
124  * @ystart: the first element in the Y array to plot (usually 0)
125  * @xstride: successive elements in the X array are separated by this much (1 if array, ncols if matrix)
126  * @ystride: successive elements in the Y array are separated by this much (1 if array, ncols if matrix)
127  * @xtype: the GType of the X array elements.  G_TYPE_FLOAT, G_TYPE_DOUBLE, etc.
128  * @ytype: the GType of the Y array elements.  G_TYPE_FLOAT, G_TYPE_DOUBLE, etc.
129  * @color: color of the markers
130  * @size: marker size or line width (depending on the @type)
131  *
132  * Creates a new #GtkDataboxLines object which can be added to a #GtkDatabox widget.
133  *
134  * Return value: A new #GtkDataboxLines object
135  **/
136 GtkDataboxGraph *
gtk_databox_lines_new_full(guint maxlen,guint len,void * X,guint xstart,guint xstride,GType xtype,void * Y,guint ystart,guint ystride,GType ytype,GdkRGBA * color,guint size)137 gtk_databox_lines_new_full (guint maxlen, guint len,
138 			void * X, guint xstart, guint xstride, GType xtype,
139 			void * Y, guint ystart, guint ystride, GType ytype,
140 		    GdkRGBA * color, guint size)
141 {
142    GtkDataboxLines *lines;
143    g_return_val_if_fail (X, NULL);
144    g_return_val_if_fail (Y, NULL);
145    g_return_val_if_fail ((len > 0), NULL);
146 
147    lines = g_object_new (GTK_DATABOX_TYPE_LINES,
148 			 "X-Values", X,
149 			 "Y-Values", Y,
150 			 "xstart", xstart,
151 			 "ystart", ystart,
152 			 "xstride", xstride,
153 			 "ystride", ystride,
154 			 "xtype", xtype,
155 			 "ytype", ytype,
156 			 "length", len,
157 			 "maxlen", maxlen,
158 			 "color", color, "size", size, NULL);
159 
160    return GTK_DATABOX_GRAPH (lines);
161 }
162 
163 static void
gtk_databox_lines_real_draw(GtkDataboxGraph * graph,GtkDatabox * box)164 gtk_databox_lines_real_draw (GtkDataboxGraph * graph,
165 			     GtkDatabox * box)
166 {
167    GtkDataboxLines *lines = GTK_DATABOX_LINES (graph);
168    GtkDataboxLinesPrivate *priv=GTK_DATABOX_LINES_GET_PRIVATE(graph);
169    guint i = 0;
170    void *X;
171    void *Y;
172    guint len, maxlen;
173    cairo_t *cr;
174    gint16 *xpixels, *ypixels;
175    guint xstart, xstride, ystart, ystride;
176    GType xtype, ytype;
177    float linewidth;
178 
179    g_return_if_fail (GTK_DATABOX_IS_LINES (lines));
180    g_return_if_fail (GTK_IS_DATABOX (box));
181 
182    len = gtk_databox_xyc_graph_get_length (GTK_DATABOX_XYC_GRAPH (graph));
183    maxlen = gtk_databox_xyc_graph_get_maxlen (GTK_DATABOX_XYC_GRAPH (graph));
184 
185    if (priv->pixelsalloc < len)
186    {
187    	priv->pixelsalloc = len;
188 	priv->xpixels = (gint16 *)g_realloc(priv->xpixels, len * sizeof(gint16));
189 	priv->ypixels = (gint16 *)g_realloc(priv->ypixels, len * sizeof(gint16));
190    }
191 
192    xpixels = priv->xpixels;
193    ypixels = priv->ypixels;
194 
195    X = gtk_databox_xyc_graph_get_X (GTK_DATABOX_XYC_GRAPH (graph));
196    xstart = gtk_databox_xyc_graph_get_xstart (GTK_DATABOX_XYC_GRAPH (graph));
197    xstride = gtk_databox_xyc_graph_get_xstride (GTK_DATABOX_XYC_GRAPH (graph));
198    xtype = gtk_databox_xyc_graph_get_xtype (GTK_DATABOX_XYC_GRAPH (graph));
199    gtk_databox_values_to_xpixels(box, xpixels, X, xtype, maxlen, xstart, xstride, len);
200 
201    Y = gtk_databox_xyc_graph_get_Y (GTK_DATABOX_XYC_GRAPH (graph));
202    ystart = gtk_databox_xyc_graph_get_ystart (GTK_DATABOX_XYC_GRAPH (graph));
203    ystride = gtk_databox_xyc_graph_get_ystride (GTK_DATABOX_XYC_GRAPH (graph));
204    ytype = gtk_databox_xyc_graph_get_ytype (GTK_DATABOX_XYC_GRAPH (graph));
205    gtk_databox_values_to_ypixels(box, ypixels, Y, ytype, maxlen, ystart, ystride, len);
206 
207    cr = gtk_databox_graph_create_gc (graph, box);
208 
209    linewidth = gtk_databox_graph_get_size (graph);
210    cairo_set_line_width(cr, linewidth + 0.1);
211 
212    cairo_move_to(cr, xpixels[0] + 0.5, ypixels[0] + 0.5);
213    for (i = 1; i < len; i++)
214 	  cairo_line_to(cr, xpixels[i] + 0.5, ypixels[i] + 0.5);
215 
216    cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
217    cairo_stroke(cr);
218    cairo_destroy(cr);
219 
220    return;
221 }
222