]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellrendererspinner.c
cellrendererspinner: Ignore deprecation warnings
[~andy/gtk] / gtk / gtkcellrendererspinner.c
1 /* GTK - The GIMP Toolkit
2  *
3  * Copyright (C) 2009 Matthias Clasen <mclasen@redhat.com>
4  * Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
5  * Copyright (C) 2009 Bastien Nocera <hadess@hadess.net>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA  02111-1307, USA.
21  */
22
23 /*
24  * Modified by the GTK+ Team and others 2007.  See the AUTHORS
25  * file for a list of people on the GTK+ Team.  See the ChangeLog
26  * files for a list of changes.  These files are distributed with
27  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
28  */
29
30 #include "config.h"
31
32 #include "gtkcellrendererspinner.h"
33 #include "gtkiconfactory.h"
34 #include "gtkicontheme.h"
35 #include "gtktypebuiltins.h"
36 #include "gtkintl.h"
37
38 #undef GDK_DEPRECATED
39 #undef GDK_DEPRECATED_FOR
40 #define GDK_DEPRECATED
41 #define GDK_DEPRECATED_FOR(f)
42 #undef GTK_DISABLE_DEPRECATED
43
44 #include "deprecated/gtkstyle.h"
45
46
47 /**
48  * SECTION:gtkcellrendererspinner
49  * @Short_description: Renders a spinning animation in a cell
50  * @Title: GtkCellRendererSpinner
51  * @See_also: #GtkSpinner, #GtkCellRendererProgress
52  *
53  * GtkCellRendererSpinner renders a spinning animation in a cell, very
54  * similar to #GtkSpinner. It can often be used as an alternative
55  * to a #GtkCellRendererProgress for displaying indefinite activity,
56  * instead of actual progress.
57  *
58  * To start the animation in a cell, set the #GtkCellRendererSpinner:active
59  * property to %TRUE and increment the #GtkCellRendererSpinner:pulse property
60  * at regular intervals. The usual way to set the cell renderer properties
61  * for each cell is to bind them to columns in your tree model using e.g.
62  * gtk_tree_view_column_add_attribute().
63  */
64
65
66 enum {
67   PROP_0,
68   PROP_ACTIVE,
69   PROP_PULSE,
70   PROP_SIZE
71 };
72
73 struct _GtkCellRendererSpinnerPrivate
74 {
75   gboolean active;
76   guint pulse;
77   GtkIconSize icon_size, old_icon_size;
78   gint size;
79 };
80
81
82 static void gtk_cell_renderer_spinner_get_property (GObject         *object,
83                                                     guint            param_id,
84                                                     GValue          *value,
85                                                     GParamSpec      *pspec);
86 static void gtk_cell_renderer_spinner_set_property (GObject         *object,
87                                                     guint            param_id,
88                                                     const GValue    *value,
89                                                     GParamSpec      *pspec);
90 static void gtk_cell_renderer_spinner_get_size     (GtkCellRenderer *cell,
91                                                     GtkWidget          *widget,
92                                                     const GdkRectangle *cell_area,
93                                                     gint               *x_offset,
94                                                     gint               *y_offset,
95                                                     gint               *width,
96                                                     gint               *height);
97 static void gtk_cell_renderer_spinner_render       (GtkCellRenderer      *cell,
98                                                     cairo_t              *cr,
99                                                     GtkWidget            *widget,
100                                                     const GdkRectangle   *background_area,
101                                                     const GdkRectangle   *cell_area,
102                                                     GtkCellRendererState  flags);
103
104 G_DEFINE_TYPE (GtkCellRendererSpinner, gtk_cell_renderer_spinner, GTK_TYPE_CELL_RENDERER)
105
106 static void
107 gtk_cell_renderer_spinner_class_init (GtkCellRendererSpinnerClass *klass)
108 {
109   GObjectClass *object_class = G_OBJECT_CLASS (klass);
110   GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
111
112   object_class->get_property = gtk_cell_renderer_spinner_get_property;
113   object_class->set_property = gtk_cell_renderer_spinner_set_property;
114
115   cell_class->get_size = gtk_cell_renderer_spinner_get_size;
116   cell_class->render = gtk_cell_renderer_spinner_render;
117
118   /* GtkCellRendererSpinner:active:
119    *
120    * Whether the spinner is active (ie. shown) in the cell
121    *
122    * Since: 2.20
123    */
124   g_object_class_install_property (object_class,
125                                    PROP_ACTIVE,
126                                    g_param_spec_boolean ("active",
127                                                          P_("Active"),
128                                                          P_("Whether the spinner is active (ie. shown) in the cell"),
129                                                          FALSE,
130                                                          G_PARAM_READWRITE));
131   /**
132    * GtkCellRendererSpinner:pulse:
133    *
134    * Pulse of the spinner. Increment this value to draw the next frame of the
135    * spinner animation. Usually, you would update this value in a timeout.
136    *
137    * By default, the #GtkSpinner widget draws one full cycle of the animation,
138    * consisting of 12 frames, in 750 milliseconds.
139    *
140    * Since: 2.20
141    */
142   g_object_class_install_property (object_class,
143                                    PROP_PULSE,
144                                    g_param_spec_uint ("pulse",
145                                                       P_("Pulse"),
146                                                       P_("Pulse of the spinner"),
147                                                       0, G_MAXUINT, 0,
148                                                       G_PARAM_READWRITE));
149   /**
150    * GtkCellRendererSpinner:size:
151    *
152    * The #GtkIconSize value that specifies the size of the rendered spinner.
153    *
154    * Since: 2.20
155    */
156   g_object_class_install_property (object_class,
157                                    PROP_SIZE,
158                                    g_param_spec_enum ("size",
159                                                       P_("Size"),
160                                                       P_("The GtkIconSize value that specifies the size of the rendered spinner"),
161                                                       GTK_TYPE_ICON_SIZE, GTK_ICON_SIZE_MENU,
162                                                       G_PARAM_READWRITE));
163
164
165   g_type_class_add_private (object_class, sizeof (GtkCellRendererSpinnerPrivate));
166 }
167
168 static void
169 gtk_cell_renderer_spinner_init (GtkCellRendererSpinner *cell)
170 {
171   cell->priv = G_TYPE_INSTANCE_GET_PRIVATE (cell,
172                                             GTK_TYPE_CELL_RENDERER_SPINNER,
173                                             GtkCellRendererSpinnerPrivate);
174
175   cell->priv->pulse = 0;
176   cell->priv->old_icon_size = GTK_ICON_SIZE_INVALID;
177   cell->priv->icon_size = GTK_ICON_SIZE_MENU;
178 }
179
180 /**
181  * gtk_cell_renderer_spinner_new:
182  *
183  * Returns a new cell renderer which will show a spinner to indicate
184  * activity.
185  *
186  * Return value: a new #GtkCellRenderer
187  *
188  * Since: 2.20
189  */
190 GtkCellRenderer *
191 gtk_cell_renderer_spinner_new (void)
192 {
193   return g_object_new (GTK_TYPE_CELL_RENDERER_SPINNER, NULL);
194 }
195
196 static void
197 gtk_cell_renderer_spinner_update_size (GtkCellRendererSpinner *cell,
198                                        GtkWidget              *widget)
199 {
200   GtkCellRendererSpinnerPrivate *priv = cell->priv;
201   GdkScreen *screen;
202   GtkSettings *settings;
203
204   if (priv->old_icon_size == priv->icon_size)
205     return;
206
207   screen = gtk_widget_get_screen (GTK_WIDGET (widget));
208   settings = gtk_settings_get_for_screen (screen);
209
210   if (!gtk_icon_size_lookup_for_settings (settings, priv->icon_size, &priv->size, NULL))
211     {
212       g_warning ("Invalid icon size %u\n", priv->icon_size);
213       priv->size = 24;
214     }
215 }
216
217 static void
218 gtk_cell_renderer_spinner_get_property (GObject    *object,
219                                         guint       param_id,
220                                         GValue     *value,
221                                         GParamSpec *pspec)
222 {
223   GtkCellRendererSpinner *cell = GTK_CELL_RENDERER_SPINNER (object);
224   GtkCellRendererSpinnerPrivate *priv = cell->priv;
225
226   switch (param_id)
227     {
228       case PROP_ACTIVE:
229         g_value_set_boolean (value, priv->active);
230         break;
231       case PROP_PULSE:
232         g_value_set_uint (value, priv->pulse);
233         break;
234       case PROP_SIZE:
235         g_value_set_enum (value, priv->icon_size);
236         break;
237       default:
238         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
239     }
240 }
241
242 static void
243 gtk_cell_renderer_spinner_set_property (GObject      *object,
244                                         guint         param_id,
245                                         const GValue *value,
246                                         GParamSpec   *pspec)
247 {
248   GtkCellRendererSpinner *cell = GTK_CELL_RENDERER_SPINNER (object);
249   GtkCellRendererSpinnerPrivate *priv = cell->priv;
250
251   switch (param_id)
252     {
253       case PROP_ACTIVE:
254         priv->active = g_value_get_boolean (value);
255         break;
256       case PROP_PULSE:
257         priv->pulse = g_value_get_uint (value);
258         break;
259       case PROP_SIZE:
260         priv->old_icon_size = priv->icon_size;
261         priv->icon_size = g_value_get_enum (value);
262         break;
263       default:
264         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
265     }
266 }
267
268 static void
269 gtk_cell_renderer_spinner_get_size (GtkCellRenderer    *cellr,
270                                     GtkWidget          *widget,
271                                     const GdkRectangle *cell_area,
272                                     gint               *x_offset,
273                                     gint               *y_offset,
274                                     gint               *width,
275                                     gint               *height)
276 {
277   GtkCellRendererSpinner *cell = GTK_CELL_RENDERER_SPINNER (cellr);
278   GtkCellRendererSpinnerPrivate *priv = cell->priv;
279   gdouble align;
280   gint w, h;
281   gint xpad, ypad;
282   gfloat xalign, yalign;
283   gboolean rtl;
284
285   rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
286
287   gtk_cell_renderer_spinner_update_size (cell, widget);
288
289   g_object_get (cellr,
290                 "xpad", &xpad,
291                 "ypad", &ypad,
292                 "xalign", &xalign,
293                 "yalign", &yalign,
294                 NULL);
295   w = h = priv->size;
296
297   if (cell_area)
298     {
299       if (x_offset)
300         {
301           align = rtl ? 1.0 - xalign : xalign;
302           *x_offset = align * (cell_area->width - w);
303           *x_offset = MAX (*x_offset, 0);
304         }
305       if (y_offset)
306         {
307           align = rtl ? 1.0 - yalign : yalign;
308           *y_offset = align * (cell_area->height - h);
309           *y_offset = MAX (*y_offset, 0);
310         }
311     }
312   else
313     {
314       if (x_offset)
315         *x_offset = 0;
316       if (y_offset)
317         *y_offset = 0;
318     }
319
320   if (width)
321     *width = w;
322   if (height)
323     *height = h;
324 }
325
326 static void
327 gtk_cell_renderer_spinner_render (GtkCellRenderer      *cellr,
328                                   cairo_t              *cr,
329                                   GtkWidget            *widget,
330                                   const GdkRectangle   *background_area,
331                                   const GdkRectangle   *cell_area,
332                                   GtkCellRendererState  flags)
333 {
334   GtkCellRendererSpinner *cell = GTK_CELL_RENDERER_SPINNER (cellr);
335   GtkCellRendererSpinnerPrivate *priv = cell->priv;
336   GtkStateType state;
337   GdkRectangle pix_rect;
338   GdkRectangle draw_rect;
339   gint xpad, ypad;
340
341   if (!priv->active)
342     return;
343
344   gtk_cell_renderer_spinner_get_size (cellr, widget, (GdkRectangle *) cell_area,
345                                       &pix_rect.x, &pix_rect.y,
346                                       &pix_rect.width, &pix_rect.height);
347
348   g_object_get (cellr,
349                 "xpad", &xpad,
350                 "ypad", &ypad,
351                 NULL);
352   pix_rect.x += cell_area->x + xpad;
353   pix_rect.y += cell_area->y + ypad;
354   pix_rect.width -= xpad * 2;
355   pix_rect.height -= ypad * 2;
356
357   if (!gdk_rectangle_intersect (cell_area, &pix_rect, &draw_rect))
358     return;
359
360   state = GTK_STATE_NORMAL;
361   if (gtk_widget_get_state (widget) == GTK_STATE_INSENSITIVE ||
362       !gtk_cell_renderer_get_sensitive (cellr))
363     {
364       state = GTK_STATE_INSENSITIVE;
365     }
366   else
367     {
368       if ((flags & GTK_CELL_RENDERER_SELECTED) != 0)
369         {
370           if (gtk_widget_has_focus (widget))
371             state = GTK_STATE_SELECTED;
372           else
373             state = GTK_STATE_ACTIVE;
374         }
375       else
376         state = GTK_STATE_PRELIGHT;
377     }
378
379   cairo_save (cr);
380
381   gdk_cairo_rectangle (cr, cell_area);
382   cairo_clip (cr);
383
384   gtk_paint_spinner (gtk_widget_get_style (widget),
385                            cr,
386                            state,
387                            widget,
388                            "cell",
389                            priv->pulse,
390                            draw_rect.x, draw_rect.y,
391                            draw_rect.width, draw_rect.height);
392
393   cairo_restore (cr);
394 }