2 * This file is part of the sigrok project.
4 * Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
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 General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "gtkcellrenderersignal.h"
34 struct _GtkCellRendererSignalPrivate
43 static void gtk_cell_renderer_signal_finalize(GObject *object);
44 static void gtk_cell_renderer_signal_get_property(GObject *object,
45 guint param_id, GValue *value,
47 static void gtk_cell_renderer_signal_set_property(GObject *object,
48 guint param_id, const GValue *value,
50 static void gtk_cell_renderer_signal_get_size(GtkCellRenderer *cell,
52 GdkRectangle *cell_area,
57 static void gtk_cell_renderer_signal_render(GtkCellRenderer *cell,
60 GdkRectangle *background_area,
61 GdkRectangle *cell_area,
62 GdkRectangle *expose_area,
63 GtkCellRendererState flags);
66 G_DEFINE_TYPE(GtkCellRendererSignal, gtk_cell_renderer_signal, GTK_TYPE_CELL_RENDERER);
69 gtk_cell_renderer_signal_class_init (GtkCellRendererSignalClass *klass)
71 GObjectClass *object_class = G_OBJECT_CLASS (klass);
72 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
74 object_class->finalize = gtk_cell_renderer_signal_finalize;
75 object_class->get_property = gtk_cell_renderer_signal_get_property;
76 object_class->set_property = gtk_cell_renderer_signal_set_property;
78 cell_class->get_size = gtk_cell_renderer_signal_get_size;
79 cell_class->render = gtk_cell_renderer_signal_render;
81 g_object_class_install_property(object_class,
83 g_param_spec_pointer("data",
85 "Binary samples data",
88 g_object_class_install_property (object_class,
90 g_param_spec_int("probe",
92 "Bit in Data to display",
96 g_object_class_install_property (object_class,
98 g_param_spec_string("foreground",
104 g_object_class_install_property (object_class,
106 g_param_spec_double("scale",
112 g_object_class_install_property (object_class,
114 g_param_spec_int("offset",
120 g_type_class_add_private (object_class,
121 sizeof (GtkCellRendererSignalPrivate));
124 static void gtk_cell_renderer_signal_init(GtkCellRendererSignal *cel)
126 GtkCellRendererSignalPrivate *priv;
128 cel->priv = G_TYPE_INSTANCE_GET_PRIVATE(cel,
129 GTK_TYPE_CELL_RENDERER_SIGNAL,
130 GtkCellRendererSignalPrivate);
139 GtkCellRenderer *gtk_cell_renderer_signal_new(void)
141 return g_object_new(GTK_TYPE_CELL_RENDERER_SIGNAL, NULL);
144 static void gtk_cell_renderer_signal_finalize(GObject *object)
146 GtkCellRendererSignal *cel = GTK_CELL_RENDERER_SIGNAL(object);
147 GtkCellRendererSignalPrivate *priv = cel->priv;
148 /* Keep this around, because it'll be useful in future */
150 G_OBJECT_CLASS(gtk_cell_renderer_signal_parent_class)->finalize(object);
154 gtk_cell_renderer_signal_get_property(GObject *object,
159 GtkCellRendererSignal *cel = GTK_CELL_RENDERER_SIGNAL(object);
160 GtkCellRendererSignalPrivate *priv = cel->priv;
164 g_value_set_pointer(value, priv->data);
167 g_value_set_int(value, priv->probe);
170 g_value_set_double(value, priv->scale);
173 g_value_set_int(value, priv->offset);
176 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
181 gtk_cell_renderer_signal_set_property(GObject *object,
186 GtkCellRendererSignal *cel = GTK_CELL_RENDERER_SIGNAL(object);
187 GtkCellRendererSignalPrivate *priv = cel->priv;
191 priv->data = g_value_get_pointer(value);
194 priv->probe = g_value_get_int(value);
196 case PROP_FOREGROUND:
197 gdk_color_parse(g_value_get_string(value), &priv->foreground);
200 priv->scale = g_value_get_double(value);
203 priv->offset = g_value_get_int(value);
206 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
211 gtk_cell_renderer_signal_get_size(GtkCellRenderer *cell,
213 GdkRectangle *cell_area,
223 /* FIXME: What about cell_area? */
224 if (width) *width = 0;
225 if (height) *height = 30;
227 if (x_offset) *x_offset = 0;
228 if (y_offset) *y_offset = 0;
232 static gboolean sample(GArray *data, gint probe, guint i)
234 int unitsize = g_array_get_element_size(data);
235 g_return_val_if_fail(i < data->len, FALSE);
236 g_return_val_if_fail(probe < unitsize * 8, FALSE);
238 return data->data[(i*unitsize) + probe/8] & (1 << (probe & 7));
242 gtk_cell_renderer_signal_render(GtkCellRenderer *cell,
245 GdkRectangle *background_area,
246 GdkRectangle *cell_area,
247 GdkRectangle *expose_area,
248 GtkCellRendererState flags)
250 GtkCellRendererSignal *cel = GTK_CELL_RENDERER_SIGNAL(cell);
251 GtkCellRendererSignalPrivate *priv= cel->priv;
252 guint nsamples = priv->data->len;
262 gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
263 x = cell_area->x + xpad;
264 y = cell_area->y + ypad;
265 w = cell_area->width - xpad * 2;
266 h = cell_area->height - ypad * 2;
268 cairo_t *cr = gdk_cairo_create(GDK_DRAWABLE(window));
270 /* Set clipping region to background rectangle.
271 * This prevents us drawing over other cells.
274 gdk_cairo_rectangle(cr, background_area);
277 cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
278 gdk_cairo_set_source_color(cr, &priv->foreground);
279 /*cairo_set_line_width(cr, 1);*/
282 si = priv->offset / priv->scale;
285 o = x - (priv->offset - si * priv->scale);
287 guint32 oldsample = sample(priv->data, priv->probe, si++);
288 cairo_move_to(cr, o, y +
289 (oldsample ? 0 : h));
292 while ((si < nsamples) && (o - priv->scale < x+w)) {
293 guint32 cursample = sample(priv->data, priv->probe, si);
294 if (cursample != oldsample) {
295 cairo_line_to(cr, o - priv->scale/8, y +
296 (oldsample ? 0 : h));
297 cairo_line_to(cr, o + priv->scale/8, y +
298 (cursample ? 0 : h));
299 oldsample = cursample;
304 cairo_line_to(cr, o - priv->scale/8, y +
305 (oldsample ? 0 : h));