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