]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellrendererprogress.c
Add a translator hint. (#163889)
[~andy/gtk] / gtk / gtkcellrendererprogress.c
1 /* gtkcellrendererprogress.c
2  * Copyright (C) 2002 Naba Kumar <kh_naba@users.sourceforge.net>
3  * heavily modified by Jörgen Scheibengruber <mfcn@gmx.de>
4  * heavily modified by Marco Pesenti Gritti <marco@gnome.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library 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 GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 /*
22  * Modified by the GTK+ Team and others 1997-2004.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 #include "config.h"
29 #include <stdlib.h>
30
31 #include "gtkalias.h"
32 #include "gtkcellrendererprogress.h"
33 #include "gtkintl.h"
34
35 #define GTK_CELL_RENDERER_PROGRESS_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object),                        \
36                                                                                      GTK_TYPE_CELL_RENDERER_PROGRESS, \
37                                                                                      GtkCellRendererProgressPrivate))
38
39 enum
40 {
41         PROP_0,
42         PROP_VALUE,
43         PROP_TEXT
44 }; 
45
46 struct _GtkCellRendererProgressPrivate
47 {
48   gint value;
49   gchar *text;
50   gchar *label;
51   gint min_h;
52   gint min_w;
53 };
54
55 static void gtk_cell_renderer_progress_finalize     (GObject                 *object);
56 static void gtk_cell_renderer_progress_get_property (GObject                 *object,
57                                                      guint                    param_id,
58                                                      GValue                  *value,
59                                                      GParamSpec              *pspec);
60 static void gtk_cell_renderer_progress_set_property (GObject                 *object,
61                                                      guint                    param_id,
62                                                      const GValue            *value,
63                                                      GParamSpec              *pspec);
64 static void gtk_cell_renderer_progress_set_value    (GtkCellRendererProgress *cellprogress,
65                                                      gint                     value);
66 static void gtk_cell_renderer_progress_set_text     (GtkCellRendererProgress *cellprogress,
67                                                      const gchar             *text);
68 static void compute_dimensions                      (GtkCellRenderer         *cell,
69                                                      GtkWidget               *widget,
70                                                      const gchar             *text,
71                                                      gint                    *width,
72                                                      gint                    *height);
73 static void gtk_cell_renderer_progress_get_size     (GtkCellRenderer         *cell,
74                                                      GtkWidget               *widget,
75                                                      GdkRectangle            *cell_area,
76                                                      gint                    *x_offset,
77                                                      gint                    *y_offset,
78                                                      gint                    *width,
79                                                      gint                    *height);
80 static void gtk_cell_renderer_progress_render       (GtkCellRenderer         *cell,
81                                                      GdkWindow               *window,
82                                                      GtkWidget               *widget,
83                                                      GdkRectangle            *background_area,
84                                                      GdkRectangle            *cell_area,
85                                                      GdkRectangle            *expose_area,
86                                                      guint                    flags);
87
88      
89 G_DEFINE_TYPE (GtkCellRendererProgress, gtk_cell_renderer_progress, GTK_TYPE_CELL_RENDERER);
90
91 static void
92 gtk_cell_renderer_progress_class_init (GtkCellRendererProgressClass *klass)
93 {
94   GObjectClass *object_class = G_OBJECT_CLASS (klass);
95   GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
96   
97   object_class->finalize = gtk_cell_renderer_progress_finalize;
98   object_class->get_property = gtk_cell_renderer_progress_get_property;
99   object_class->set_property = gtk_cell_renderer_progress_set_property;
100   
101   cell_class->get_size = gtk_cell_renderer_progress_get_size;
102   cell_class->render = gtk_cell_renderer_progress_render;
103   
104   /**
105    * GtkCellRendererProgress:value:
106    * 
107    * The "value" property determines the percentage to which the
108    * progress bar will be "filled in". 
109    *
110    * Since: 2.6
111    **/
112   g_object_class_install_property (object_class,
113                                    PROP_VALUE,
114                                    g_param_spec_int ("value",
115                                                      P_("Value"),
116                                                      P_("Value of the progress bar"),
117                                                      0, 100, 0,
118                                                      G_PARAM_READWRITE));
119
120   /**
121    * GtkCellRendererProgress:text:
122    * 
123    * The "text" property determines the label which will be drawn
124    * over the progress bar. Setting this property to %NULL causes the default 
125    * label to be displayed. Setting this property to an empty string causes 
126    * no label to be displayed.
127    *
128    * Since: 2.6
129    **/
130   g_object_class_install_property (object_class,
131                                    PROP_TEXT,
132                                    g_param_spec_string ("text",
133                                                         P_("Text"),
134                                                         P_("Text on the progress bar"),
135                                                         NULL,
136                                                         G_PARAM_READWRITE));
137
138   g_type_class_add_private (object_class, 
139                             sizeof (GtkCellRendererProgressPrivate));
140 }
141
142 static void
143 gtk_cell_renderer_progress_init (GtkCellRendererProgress *cellprogress)
144 {
145   cellprogress->priv = GTK_CELL_RENDERER_PROGRESS_GET_PRIVATE (cellprogress);
146   cellprogress->priv->value = 0;
147   cellprogress->priv->text = NULL;
148   cellprogress->priv->label = NULL;
149   cellprogress->priv->min_w = -1;
150   cellprogress->priv->min_h = -1;
151 }
152
153
154 /**
155  * gtk_cell_renderer_progress_new:
156  * 
157  * Creates a new #GtkCellRendererProgress. 
158  *
159  * Return value: the new cell renderer
160  *
161  * Since: 2.6
162  **/
163 GtkCellRenderer*
164 gtk_cell_renderer_progress_new (void)
165 {
166   return g_object_new (GTK_TYPE_CELL_RENDERER_PROGRESS, NULL);
167 }
168
169 static void
170 gtk_cell_renderer_progress_finalize (GObject *object)
171 {
172   GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
173   
174   g_free (cellprogress->priv->text);
175   g_free (cellprogress->priv->label);
176   
177   G_OBJECT_CLASS (gtk_cell_renderer_progress_parent_class)->finalize (object);
178 }
179
180 static void
181 gtk_cell_renderer_progress_get_property (GObject *object,
182                                          guint param_id,
183                                          GValue *value,
184                                          GParamSpec *pspec)
185 {
186   GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
187   
188   switch (param_id)
189     {
190     case PROP_VALUE:
191       g_value_set_int (value, cellprogress->priv->value);
192       break;
193     case PROP_TEXT:
194       g_value_set_string (value, cellprogress->priv->text);
195       break;
196     default:
197       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
198     }
199 }
200
201 static void
202 gtk_cell_renderer_progress_set_property (GObject *object,
203                                          guint param_id,
204                                          const GValue *value,
205                                          GParamSpec   *pspec)
206 {
207   GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
208   
209   switch (param_id)
210     {
211     case PROP_VALUE:
212       gtk_cell_renderer_progress_set_value (cellprogress, 
213                                             g_value_get_int (value));
214       break;
215     case PROP_TEXT:
216       gtk_cell_renderer_progress_set_text (cellprogress,
217                                            g_value_get_string (value));
218       break;
219     default:
220       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
221     }
222 }
223
224 static void
225 gtk_cell_renderer_progress_set_value (GtkCellRendererProgress *cellprogress, 
226                                       gint                     value)
227 {
228   gchar *text;
229   
230   cellprogress->priv->value = value;
231
232   if (cellprogress->priv->text)
233     text = g_strdup (cellprogress->priv->text);
234   else
235     /* do not translate the part before the | */
236     text = g_strdup_printf (Q_("progress bar label|%d %%"), 
237                             cellprogress->priv->value);
238   
239   g_free (cellprogress->priv->label);
240   cellprogress->priv->label = text;
241 }
242
243 static void
244 gtk_cell_renderer_progress_set_text (GtkCellRendererProgress *cellprogress, 
245                                      const gchar             *text)
246 {
247   gchar *new_text;
248
249   new_text = g_strdup (text);
250   g_free (cellprogress->priv->text);
251   cellprogress->priv->text = new_text;
252
253   /* Update the label */
254   gtk_cell_renderer_progress_set_value (cellprogress, cellprogress->priv->value);
255 }
256
257 static void
258 compute_dimensions (GtkCellRenderer *cell,
259                     GtkWidget       *widget, 
260                     const gchar     *text, 
261                     gint            *width, 
262                     gint            *height)
263 {
264   PangoRectangle logical_rect;
265   PangoLayout *layout;
266   
267   layout = gtk_widget_create_pango_layout (widget, text);
268   pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
269   
270   if (width)
271     *width = logical_rect.width + cell->xpad * 2 + widget->style->xthickness * 2;
272   
273   if (height)
274     *height = logical_rect.height + cell->ypad * 2 + widget->style->ythickness * 2;
275   
276   g_object_unref (layout);
277 }
278
279 static void
280 gtk_cell_renderer_progress_get_size (GtkCellRenderer *cell,
281                                      GtkWidget       *widget,
282                                      GdkRectangle    *cell_area,
283                                      gint            *x_offset,
284                                      gint            *y_offset,
285                                      gint            *width,
286                                      gint            *height)
287 {
288   GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (cell);
289   gint w, h;
290   gchar *text;
291
292   if (cellprogress->priv->min_w < 0)
293     {
294       text = g_strdup_printf (Q_("progress bar label|%d %%"), 100);
295       compute_dimensions (cell, widget, text,
296                           &cellprogress->priv->min_w,
297                           &cellprogress->priv->min_h);
298       g_free (text);
299     }
300   
301   compute_dimensions (cell, widget, cellprogress->priv->label, &w, &h);
302   
303   if (width)
304       *width = MAX (cellprogress->priv->min_w, w);
305   
306   if (height)
307     *height = MIN (cellprogress->priv->min_h, h);
308 }
309
310 static void
311 gtk_cell_renderer_progress_render (GtkCellRenderer *cell,
312                                    GdkWindow       *window,
313                                    GtkWidget       *widget,
314                                    GdkRectangle    *background_area,
315                                    GdkRectangle    *cell_area,
316                                    GdkRectangle    *expose_area,
317                                    guint            flags)
318 {
319   GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (cell);
320   GdkGC *gc;
321   PangoLayout *layout;
322   PangoRectangle logical_rect;
323   gint x, y, w, h, perc_w, pos;
324   GdkRectangle clip;
325   gboolean is_rtl;
326
327   is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
328   
329   gc = gdk_gc_new (window);
330   
331   x = cell_area->x + cell->xpad;
332   y = cell_area->y + cell->ypad;
333   
334   w = cell_area->width - cell->xpad * 2;
335   h = cell_area->height - cell->ypad * 2;
336   
337   gdk_gc_set_rgb_fg_color (gc, &widget->style->fg[GTK_STATE_NORMAL]);
338   gdk_draw_rectangle (window, gc, TRUE, x, y, w, h);
339   
340   x += widget->style->xthickness;
341   y += widget->style->ythickness;
342   w -= widget->style->xthickness * 2;
343   h -= widget->style->ythickness * 2;
344   gdk_gc_set_rgb_fg_color (gc, &widget->style->bg[GTK_STATE_NORMAL]);
345   gdk_draw_rectangle (window, gc, TRUE, x, y, w, h);
346   
347   gdk_gc_set_rgb_fg_color (gc, &widget->style->bg[GTK_STATE_SELECTED]);
348   perc_w = w * MAX (0, cellprogress->priv->value) / 100;
349   gdk_draw_rectangle (window, gc, TRUE, is_rtl ? (x + w - perc_w) : x, y, perc_w, h);
350   
351   layout = gtk_widget_create_pango_layout (widget, cellprogress->priv->label);
352   pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
353   
354   pos = (w - logical_rect.width)/2;
355   
356   clip.x = x;
357   clip.y = y;
358   clip.width = is_rtl ? w - perc_w : perc_w;
359   clip.height = h; 
360
361   gtk_paint_layout (widget->style, window, 
362                     is_rtl ? GTK_STATE_NORMAL : GTK_STATE_SELECTED,
363                     FALSE, &clip, widget, "progressbar",
364                     x + pos, y + (h - logical_rect.height)/2,
365                     layout);
366
367   clip.x = clip.x + clip.width;
368   clip.width = w - clip.width;
369
370   gtk_paint_layout (widget->style, window, 
371                     is_rtl ?  GTK_STATE_SELECTED : GTK_STATE_NORMAL,
372                     FALSE, &clip, widget, "progressbar",
373                     x + pos, y + (h - logical_rect.height)/2,
374                     layout);
375   
376   g_object_unref (layout);
377   g_object_unref (gc);
378 }
379