d3372da9 |
1 | /* Taken from the GTK TreeView tutorial on gtk.org. |
2 | * Slightly modified. |
3 | */ |
4 | |
5 | #include "progressbar.h" |
6 | |
7 | /* This is based mainly on GtkCellRendererProgress |
8 | * in GAIM, written and (c) 2002 by Sean Egan |
9 | * (Licensed under the GPL), which in turn is |
10 | * based on Gtk's GtkCellRenderer[Text|Toggle|Pixbuf] |
11 | * implementation by Jonathan Blandford */ |
12 | |
13 | /* Some boring function declarations: GObject type system stuff */ |
14 | |
15 | static void custom_cell_renderer_progress_init (CustomCellRendererProgress *cellprogress); |
16 | |
17 | static void custom_cell_renderer_progress_class_init (CustomCellRendererProgressClass *klass); |
18 | |
19 | static void custom_cell_renderer_progress_get_property (GObject *object, |
20 | guint param_id, |
21 | GValue *value, |
22 | GParamSpec *pspec); |
23 | |
24 | static void custom_cell_renderer_progress_set_property (GObject *object, |
25 | guint param_id, |
26 | const GValue *value, |
27 | GParamSpec *pspec); |
28 | |
29 | static void custom_cell_renderer_progress_finalize (GObject *gobject); |
30 | |
31 | |
32 | /* These functions are the heart of our custom cell renderer: */ |
33 | |
34 | static void custom_cell_renderer_progress_get_size (GtkCellRenderer *cell, |
35 | GtkWidget *widget, |
36 | GdkRectangle *cell_area, |
37 | gint *x_offset, |
38 | gint *y_offset, |
39 | gint *width, |
40 | gint *height); |
41 | |
42 | static void custom_cell_renderer_progress_render (GtkCellRenderer *cell, |
43 | GdkWindow *window, |
44 | GtkWidget *widget, |
45 | GdkRectangle *background_area, |
46 | GdkRectangle *cell_area, |
47 | GdkRectangle *expose_area, |
48 | guint flags); |
49 | |
50 | |
51 | enum |
52 | { |
53 | PROP_PERCENTAGE = 1, |
54 | }; |
55 | |
56 | static gpointer parent_class; |
57 | |
58 | |
59 | /*************************************************************************** |
60 | * |
61 | * custom_cell_renderer_progress_get_type: here we register our type with |
62 | * the GObject type system if we |
63 | * haven't done so yet. Everything |
64 | * else is done in the callbacks. |
65 | * |
66 | ***************************************************************************/ |
67 | |
68 | GType |
69 | custom_cell_renderer_progress_get_type (void) |
70 | { |
71 | static GType cell_progress_type = 0; |
72 | |
73 | if (cell_progress_type) |
74 | return cell_progress_type; |
75 | |
76 | if (1) |
77 | { |
78 | static const GTypeInfo cell_progress_info = |
79 | { |
80 | sizeof (CustomCellRendererProgressClass), |
81 | NULL, /* base_init */ |
82 | NULL, /* base_finalize */ |
83 | (GClassInitFunc) custom_cell_renderer_progress_class_init, |
84 | NULL, /* class_finalize */ |
85 | NULL, /* class_data */ |
86 | sizeof (CustomCellRendererProgress), |
87 | 0, /* n_preallocs */ |
88 | (GInstanceInitFunc) custom_cell_renderer_progress_init, |
89 | }; |
90 | |
91 | /* Derive from GtkCellRenderer */ |
92 | cell_progress_type = g_type_register_static (GTK_TYPE_CELL_RENDERER, |
93 | "CustomCellRendererProgress", |
94 | &cell_progress_info, |
95 | 0); |
96 | } |
97 | |
98 | return cell_progress_type; |
99 | } |
100 | |
101 | |
102 | /*************************************************************************** |
103 | * |
104 | * custom_cell_renderer_progress_init: set some default properties of the |
105 | * parent (GtkCellRenderer). |
106 | * |
107 | ***************************************************************************/ |
108 | |
109 | static void |
110 | custom_cell_renderer_progress_init (CustomCellRendererProgress *cellrendererprogress) |
111 | { |
112 | GTK_CELL_RENDERER(cellrendererprogress)->mode = GTK_CELL_RENDERER_MODE_INERT; |
113 | GTK_CELL_RENDERER(cellrendererprogress)->xpad = 2; |
114 | GTK_CELL_RENDERER(cellrendererprogress)->ypad = 2; |
115 | } |
116 | |
117 | |
118 | /*************************************************************************** |
119 | * |
120 | * custom_cell_renderer_progress_class_init: |
121 | * |
122 | * set up our own get_property and set_property functions, and |
123 | * override the parent's functions that we need to implement. |
124 | * And make our new "percentage" property known to the type system. |
125 | * If you want cells that can be activated on their own (ie. not |
126 | * just the whole row selected) or cells that are editable, you |
127 | * will need to override 'activate' and 'start_editing' as well. |
128 | * |
129 | ***************************************************************************/ |
130 | |
131 | static void |
132 | custom_cell_renderer_progress_class_init (CustomCellRendererProgressClass *klass) |
133 | { |
134 | GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS(klass); |
135 | GObjectClass *object_class = G_OBJECT_CLASS(klass); |
136 | |
137 | parent_class = g_type_class_peek_parent (klass); |
138 | object_class->finalize = custom_cell_renderer_progress_finalize; |
139 | |
140 | /* Hook up functions to set and get our |
141 | * custom cell renderer properties */ |
142 | object_class->get_property = custom_cell_renderer_progress_get_property; |
143 | object_class->set_property = custom_cell_renderer_progress_set_property; |
144 | |
145 | /* Override the two crucial functions that are the heart |
146 | * of a cell renderer in the parent class */ |
147 | cell_class->get_size = custom_cell_renderer_progress_get_size; |
148 | cell_class->render = custom_cell_renderer_progress_render; |
149 | |
150 | /* Install our very own properties */ |
151 | g_object_class_install_property (object_class, |
152 | PROP_PERCENTAGE, |
153 | g_param_spec_double ("percentage", |
154 | "Percentage", |
155 | "The fractional progress to display", |
156 | 0, 1, 0, |
157 | G_PARAM_READWRITE)); |
158 | } |
159 | |
160 | |
161 | /*************************************************************************** |
162 | * |
163 | * custom_cell_renderer_progress_finalize: free any resources here |
164 | * |
165 | ***************************************************************************/ |
166 | |
167 | static void |
168 | custom_cell_renderer_progress_finalize (GObject *object) |
169 | { |
170 | /* |
171 | CustomCellRendererProgress *cellrendererprogress = CUSTOM_CELL_RENDERER_PROGRESS(object); |
172 | */ |
173 | |
174 | /* Free any dynamically allocated resources here */ |
175 | |
176 | (* G_OBJECT_CLASS (parent_class)->finalize) (object); |
177 | } |
178 | |
179 | |
180 | /*************************************************************************** |
181 | * |
182 | * custom_cell_renderer_progress_get_property: as it says |
183 | * |
184 | ***************************************************************************/ |
185 | |
186 | static void |
187 | custom_cell_renderer_progress_get_property (GObject *object, |
188 | guint param_id, |
189 | GValue *value, |
190 | GParamSpec *psec) |
191 | { |
192 | CustomCellRendererProgress *cellprogress = CUSTOM_CELL_RENDERER_PROGRESS(object); |
193 | |
194 | switch (param_id) |
195 | { |
196 | case PROP_PERCENTAGE: |
197 | g_value_set_double(value, cellprogress->progress); |
198 | break; |
199 | |
200 | default: |
201 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, psec); |
202 | break; |
203 | } |
204 | } |
205 | |
206 | |
207 | /*************************************************************************** |
208 | * |
209 | * custom_cell_renderer_progress_set_property: as it says |
210 | * |
211 | ***************************************************************************/ |
212 | |
213 | static void |
214 | custom_cell_renderer_progress_set_property (GObject *object, |
215 | guint param_id, |
216 | const GValue *value, |
217 | GParamSpec *pspec) |
218 | { |
219 | CustomCellRendererProgress *cellprogress = CUSTOM_CELL_RENDERER_PROGRESS (object); |
220 | |
221 | switch (param_id) |
222 | { |
223 | case PROP_PERCENTAGE: |
224 | cellprogress->progress = g_value_get_double(value); |
225 | break; |
226 | |
227 | default: |
228 | G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); |
229 | break; |
230 | } |
231 | } |
232 | |
233 | /*************************************************************************** |
234 | * |
235 | * custom_cell_renderer_progress_new: return a new cell renderer instance |
236 | * |
237 | ***************************************************************************/ |
238 | |
239 | GtkCellRenderer * |
240 | custom_cell_renderer_progress_new (void) |
241 | { |
242 | return g_object_new(CUSTOM_TYPE_CELL_RENDERER_PROGRESS, NULL); |
243 | } |
244 | |
245 | |
246 | /*************************************************************************** |
247 | * |
248 | * custom_cell_renderer_progress_get_size: crucial - calculate the size |
249 | * of our cell, taking into account |
250 | * padding and alignment properties |
251 | * of parent. |
252 | * |
253 | ***************************************************************************/ |
254 | |
255 | #define FIXED_WIDTH 100 |
256 | #define FIXED_HEIGHT 12 |
257 | |
258 | static void |
259 | custom_cell_renderer_progress_get_size (GtkCellRenderer *cell, |
260 | GtkWidget *widget, |
261 | GdkRectangle *cell_area, |
262 | gint *x_offset, |
263 | gint *y_offset, |
264 | gint *width, |
265 | gint *height) |
266 | { |
267 | gint calc_width; |
268 | gint calc_height; |
269 | |
270 | calc_width = (gint) cell->xpad * 2 + FIXED_WIDTH; |
271 | calc_height = (gint) cell->ypad * 2 + FIXED_HEIGHT; |
272 | |
273 | if (width) |
274 | *width = calc_width; |
275 | |
276 | if (height) |
277 | *height = calc_height; |
278 | |
279 | if (cell_area) |
280 | { |
281 | if (x_offset) |
282 | { |
283 | *x_offset = cell->xalign * (cell_area->width - calc_width); |
284 | *x_offset = MAX (*x_offset, 0); |
285 | } |
286 | |
287 | if (y_offset) |
288 | { |
289 | *y_offset = cell->yalign * (cell_area->height - calc_height); |
290 | *y_offset = MAX (*y_offset, 0); |
291 | } |
292 | } |
293 | } |
294 | |
295 | |
296 | /*************************************************************************** |
297 | * |
298 | * custom_cell_renderer_progress_render: crucial - do the rendering. |
299 | * |
300 | ***************************************************************************/ |
301 | |
302 | static void |
303 | custom_cell_renderer_progress_render (GtkCellRenderer *cell, |
304 | GdkWindow *window, |
305 | GtkWidget *widget, |
306 | GdkRectangle *background_area, |
307 | GdkRectangle *cell_area, |
308 | GdkRectangle *expose_area, |
309 | guint flags) |
310 | { |
311 | CustomCellRendererProgress *cellprogress = CUSTOM_CELL_RENDERER_PROGRESS (cell); |
312 | GtkStateType state; |
313 | gint width, height; |
314 | gint x_offset, y_offset; |
315 | |
316 | custom_cell_renderer_progress_get_size (cell, widget, cell_area, |
317 | &x_offset, &y_offset, |
318 | &width, &height); |
319 | |
320 | if (GTK_WIDGET_HAS_FOCUS (widget)) |
321 | state = GTK_STATE_ACTIVE; |
322 | else |
323 | state = GTK_STATE_NORMAL; |
324 | |
325 | width -= cell->xpad*2; |
326 | height -= cell->ypad*2; |
327 | |
328 | gtk_paint_box (widget->style, |
329 | window, |
330 | GTK_STATE_NORMAL, GTK_SHADOW_IN, |
331 | NULL, widget, "trough", |
332 | cell_area->x + x_offset + cell->xpad, |
333 | cell_area->y + y_offset + cell->ypad, |
334 | width - 1, height - 1); |
335 | |
336 | gtk_paint_box (widget->style, |
337 | window, |
338 | state, GTK_SHADOW_OUT, |
339 | NULL, widget, "bar", |
340 | cell_area->x + x_offset + cell->xpad, |
341 | cell_area->y + y_offset + cell->ypad, |
342 | width * cellprogress->progress, |
343 | height - 1); |
344 | } |