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