1 /* baobab-cell-renderer-progress.c
2 *
3 * Copyright (C) 2006 Paolo Borelli
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library 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 GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include "config.h"
22 #include <stdlib.h>
23
24 #include "baobab-cell-renderer-progress.h"
25
26 #define BAOBAB_CELL_RENDERER_PROGRESS_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), \
27 BAOBAB_TYPE_CELL_RENDERER_PROGRESS, \
28 BaobabCellRendererProgressPrivate))
29
30 enum
31 {
32 PROP_0,
33 PROP_PERC
34 };
35
36 struct _BaobabCellRendererProgressPrivate
37 {
38 double perc;
39 };
40
G_DEFINE_TYPE(BaobabCellRendererProgress,baobab_cell_renderer_progress,GTK_TYPE_CELL_RENDERER)41 G_DEFINE_TYPE (BaobabCellRendererProgress, baobab_cell_renderer_progress, GTK_TYPE_CELL_RENDERER)
42
43 static void
44 baobab_cell_renderer_progress_init (BaobabCellRendererProgress *cellprogress)
45 {
46 cellprogress->priv = BAOBAB_CELL_RENDERER_PROGRESS_GET_PRIVATE (cellprogress);
47 cellprogress->priv->perc = 0;
48
49 g_object_set (cellprogress,
50 "mode", GTK_CELL_RENDERER_MODE_INERT,
51 NULL);
52 gtk_cell_renderer_set_padding (GTK_CELL_RENDERER (cellprogress), 4, 4);
53 }
54
55 GtkCellRenderer*
baobab_cell_renderer_progress_new(void)56 baobab_cell_renderer_progress_new (void)
57 {
58 return g_object_new (BAOBAB_TYPE_CELL_RENDERER_PROGRESS, NULL);
59 }
60
61 static void
baobab_cell_renderer_progress_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)62 baobab_cell_renderer_progress_get_property (GObject *object,
63 guint param_id,
64 GValue *value,
65 GParamSpec *pspec)
66 {
67 BaobabCellRendererProgress *cellprogress = BAOBAB_CELL_RENDERER_PROGRESS (object);
68
69 switch (param_id)
70 {
71 case PROP_PERC:
72 g_value_set_double (value, cellprogress->priv->perc);
73 break;
74 default:
75 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
76 }
77 }
78
79 static void
baobab_cell_renderer_progress_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)80 baobab_cell_renderer_progress_set_property (GObject *object,
81 guint param_id,
82 const GValue *value,
83 GParamSpec *pspec)
84 {
85 BaobabCellRendererProgress *cellprogress = BAOBAB_CELL_RENDERER_PROGRESS (object);
86
87 switch (param_id)
88 {
89 case PROP_PERC:
90 cellprogress->priv->perc = g_value_get_double (value);
91 break;
92 default:
93 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
94 }
95 }
96
97 /* we simply have a fixed size */
98
99 #define FIXED_WIDTH 70
100 #define FIXED_HEIGHT 8
101
102 static void
baobab_cell_renderer_progress_get_size(GtkCellRenderer * cell,GtkWidget * widget,const GdkRectangle * cell_area,gint * x_offset,gint * y_offset,gint * width,gint * height)103 baobab_cell_renderer_progress_get_size (GtkCellRenderer *cell,
104 GtkWidget *widget,
105 const GdkRectangle *cell_area,
106 gint *x_offset,
107 gint *y_offset,
108 gint *width,
109 gint *height)
110 {
111 gint calc_width, calc_height;
112 gint xpad, ypad;
113 gfloat xalign, yalign;
114
115 gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
116
117 calc_width = xpad * 2 + FIXED_WIDTH;
118 calc_height = ypad * 2 + FIXED_HEIGHT;
119
120 if (width)
121 *width = calc_width;
122
123 if (height)
124 *height = calc_height;
125
126 gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
127 if (cell_area)
128 {
129 if (x_offset)
130 {
131 *x_offset = xalign * (cell_area->width - calc_width);
132 *x_offset = MAX (*x_offset, 0);
133 }
134
135 if (y_offset)
136 {
137 *y_offset = yalign * (cell_area->height - calc_height);
138 *y_offset = MAX (*y_offset, 0);
139 }
140 }
141 }
142
143 static void
set_color_according_to_perc(cairo_t * cr,double value)144 set_color_according_to_perc (cairo_t *cr, double value)
145 {
146 static GdkColor red;
147 static GdkColor yellow;
148 static GdkColor green;
149 static gboolean colors_initialized = FALSE;
150
151 if (!colors_initialized)
152 {
153 /* hardcoded tango colors */
154 gdk_color_parse ("#cc0000", &red);
155 gdk_color_parse ("#edd400", &yellow);
156 gdk_color_parse ("#73d216", &green);
157
158 colors_initialized = TRUE;
159 }
160
161 if (value <= 0)
162 {
163 cairo_set_source_rgb (cr, 1, 1, 1);
164 return;
165 }
166 else if (value <= 33.33)
167 {
168 gdk_cairo_set_source_color (cr, &green);
169 return;
170 }
171 else if (value <= 66.66)
172 {
173 gdk_cairo_set_source_color (cr, &yellow);
174 return;
175 }
176 else if (value <= 100.0)
177 {
178 gdk_cairo_set_source_color (cr, &red);
179 return;
180 }
181 else
182 g_assert_not_reached ();
183 }
184
185 static void
baobab_cell_renderer_progress_render(GtkCellRenderer * cell,cairo_t * cr,GtkWidget * widget,const GdkRectangle * background_area,const GdkRectangle * cell_area,GtkCellRendererState flags)186 baobab_cell_renderer_progress_render (GtkCellRenderer *cell,
187 cairo_t *cr,
188 GtkWidget *widget,
189 const GdkRectangle *background_area,
190 const GdkRectangle *cell_area,
191 GtkCellRendererState flags)
192 {
193 BaobabCellRendererProgress *cellprogress = BAOBAB_CELL_RENDERER_PROGRESS (cell);
194 gint x, y, w, h, perc_w;
195 gint xpad, ypad;
196 gboolean is_rtl;
197
198 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
199
200 gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
201 x = cell_area->x + xpad;
202 y = cell_area->y + ypad;
203
204 w = cell_area->width - xpad * 2;
205 h = cell_area->height - ypad * 2;
206
207 /*
208 * we always use a white bar with black
209 * border and green/yellow/red progress...
210 * I know it's not theme friendly, but we don't
211 * want a plain progress bar
212 */
213
214 cairo_rectangle (cr, x, y, w, h);
215 cairo_set_source_rgb (cr, 1, 1, 1);
216 cairo_fill (cr);
217
218 perc_w = w * MAX (0, cellprogress->priv->perc) / 100;
219
220 cairo_rectangle (cr, is_rtl ? (x + w - perc_w) : x, y, perc_w, h);
221 set_color_according_to_perc (cr, cellprogress->priv->perc);
222 cairo_fill (cr);
223
224 cairo_rectangle (cr, x, y, w, h);
225 cairo_set_source_rgb (cr, 0, 0, 0);
226 cairo_fill (cr);
227 }
228
229 static void
baobab_cell_renderer_progress_class_init(BaobabCellRendererProgressClass * klass)230 baobab_cell_renderer_progress_class_init (BaobabCellRendererProgressClass *klass)
231 {
232 GObjectClass *object_class = G_OBJECT_CLASS (klass);
233 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
234
235 object_class->get_property = baobab_cell_renderer_progress_get_property;
236 object_class->set_property = baobab_cell_renderer_progress_set_property;
237
238 cell_class->get_size = baobab_cell_renderer_progress_get_size;
239 cell_class->render = baobab_cell_renderer_progress_render;
240
241 g_object_class_install_property (object_class,
242 PROP_PERC,
243 g_param_spec_double ("perc",
244 "percentage",
245 "precentage",
246 -1, 100, 0,
247 G_PARAM_READWRITE));
248
249 g_type_class_add_private (object_class,
250 sizeof (BaobabCellRendererProgressPrivate));
251 }
252