]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellrenderertoggle.c
remove debugging spew
[~andy/gtk] / gtk / gtkcellrenderertoggle.c
1 /* gtkcellrenderertoggle.c
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <stdlib.h>
21 #include <gtk/gtkcellrenderertoggle.h>
22 #include <gtk/gtksignal.h>
23 #include "gtkintl.h"
24
25 static void gtk_cell_renderer_toggle_get_property  (GObject                    *object,
26                                                     guint                       param_id,
27                                                     GValue                     *value,
28                                                     GParamSpec                 *pspec);
29 static void gtk_cell_renderer_toggle_set_property  (GObject                    *object,
30                                                     guint                       param_id,
31                                                     const GValue               *value,
32                                                     GParamSpec                 *pspec);
33 static void gtk_cell_renderer_toggle_init       (GtkCellRendererToggle      *celltext);
34 static void gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class);
35 static void gtk_cell_renderer_toggle_get_size   (GtkCellRenderer            *cell,
36                                                  GtkWidget                  *widget,
37                                                  GdkRectangle               *cell_area,
38                                                  gint                       *x_offset,
39                                                  gint                       *y_offset,
40                                                  gint                       *width,
41                                                  gint                       *height);
42 static void gtk_cell_renderer_toggle_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 static gint gtk_cell_renderer_toggle_event      (GtkCellRenderer            *cell,
50                                                  GdkEvent                   *event,
51                                                  GtkWidget                  *widget,
52                                                  gchar                      *path,
53                                                  GdkRectangle               *background_area,
54                                                  GdkRectangle               *cell_area,
55                                                  guint                       flags);
56
57
58 enum {
59   TOGGLED,
60   LAST_SIGNAL
61 };
62
63 enum {
64   PROP_ZERO,
65   PROP_ACTIVE,
66   PROP_RADIO
67 };
68
69
70 #define TOGGLE_WIDTH 12
71
72 static guint toggle_cell_signals[LAST_SIGNAL] = { 0 };
73
74
75 GtkType
76 gtk_cell_renderer_toggle_get_type (void)
77 {
78   static GtkType cell_toggle_type = 0;
79
80   if (!cell_toggle_type)
81     {
82       static const GTypeInfo cell_toggle_info =
83       {
84         sizeof (GtkCellRendererToggleClass),
85         NULL,           /* base_init */
86         NULL,           /* base_finalize */
87         (GClassInitFunc) gtk_cell_renderer_toggle_class_init,
88         NULL,           /* class_finalize */
89         NULL,           /* class_data */
90         sizeof (GtkCellRendererToggle),
91         0,              /* n_preallocs */
92         (GInstanceInitFunc) gtk_cell_renderer_toggle_init,
93       };
94
95       cell_toggle_type = g_type_register_static (GTK_TYPE_CELL_RENDERER, "GtkCellRendererToggle", &cell_toggle_info, 0);
96     }
97
98   return cell_toggle_type;
99 }
100
101 static void
102 gtk_cell_renderer_toggle_init (GtkCellRendererToggle *celltoggle)
103 {
104   celltoggle->active = FALSE;
105   celltoggle->radio = FALSE;
106   GTK_CELL_RENDERER (celltoggle)->can_activate = TRUE;
107   GTK_CELL_RENDERER (celltoggle)->xpad = 2;
108   GTK_CELL_RENDERER (celltoggle)->ypad = 2;
109 }
110
111 static void
112 gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class)
113 {
114   GObjectClass *object_class = G_OBJECT_CLASS (class);
115   GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
116
117   object_class->get_property = gtk_cell_renderer_toggle_get_property;
118   object_class->set_property = gtk_cell_renderer_toggle_set_property;
119
120   cell_class->get_size = gtk_cell_renderer_toggle_get_size;
121   cell_class->render = gtk_cell_renderer_toggle_render;
122   cell_class->event = gtk_cell_renderer_toggle_event;
123   
124   g_object_class_install_property (object_class,
125                                    PROP_ACTIVE,
126                                    g_param_spec_boolean ("active",
127                                                          _("Toggle state"),
128                                                          _("The toggle state of the button"),
129                                                          FALSE,
130                                                          G_PARAM_READABLE |
131                                                          G_PARAM_WRITABLE));
132   
133   g_object_class_install_property (object_class,
134                                    PROP_RADIO,
135                                    g_param_spec_boolean ("radio",
136                                                          _("Radio state"),
137                                                          _("Draw the toggle button as a radio button"),
138                                                          FALSE,
139                                                          G_PARAM_READABLE |
140                                                          G_PARAM_WRITABLE));
141
142
143   toggle_cell_signals[TOGGLED] =
144     gtk_signal_new ("toggled",
145                     GTK_RUN_LAST,
146                     GTK_CLASS_TYPE (object_class),
147                     GTK_SIGNAL_OFFSET (GtkCellRendererToggleClass, toggled),
148                     gtk_marshal_VOID__POINTER,
149                     GTK_TYPE_NONE, 1,
150                     GTK_TYPE_POINTER);
151 }
152
153 static void
154 gtk_cell_renderer_toggle_get_property (GObject     *object,
155                                        guint        param_id,
156                                        GValue      *value,
157                                        GParamSpec  *pspec)
158 {
159   GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (object);
160   
161   switch (param_id)
162     {
163     case PROP_ACTIVE:
164       g_value_set_boolean (value, celltoggle->active);
165       break;
166     case PROP_RADIO:
167       g_value_set_boolean (value, celltoggle->radio);
168       break;
169     default:
170       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
171       break;
172     }
173 }
174
175
176 static void
177 gtk_cell_renderer_toggle_set_property (GObject      *object,
178                                        guint         param_id,
179                                        const GValue *value,
180                                        GParamSpec   *pspec)
181 {
182   GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (object);
183   
184   switch (param_id)
185     {
186     case PROP_ACTIVE:
187       celltoggle->active = g_value_get_boolean (value);
188       g_object_notify (G_OBJECT(object), "active");
189       break;
190     case PROP_RADIO:
191       celltoggle->radio = g_value_get_boolean (value);
192       g_object_notify (G_OBJECT(object), "radio");
193       break;
194     default:
195       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
196       break;
197     }
198 }
199
200 /**
201  * gtk_cell_renderer_toggle_new:
202  * 
203  * Creates a new #GtkCellRendererToggle. Adjust rendering
204  * parameters using object properties. Object properties can be set
205  * globally (with g_object_set()). Also, with #GtkTreeViewColumn, you
206  * can bind a property to a value in a #GtkTreeModel. For example, you
207  * can bind the "active" property on the cell renderer to a boolean value
208  * in the model, thus causing the check button to reflect the state of
209  * the model.
210  * 
211  * Return value: the new cell renderer
212  **/
213 GtkCellRenderer *
214 gtk_cell_renderer_toggle_new (void)
215 {
216   return GTK_CELL_RENDERER (gtk_type_new (gtk_cell_renderer_toggle_get_type ()));
217 }
218
219 static void
220 gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell,
221                                    GtkWidget       *widget,
222                                    GdkRectangle    *cell_area,
223                                    gint            *x_offset,
224                                    gint            *y_offset,
225                                    gint            *width,
226                                    gint            *height)
227 {
228   gint calc_width;
229   gint calc_height;
230
231   calc_width = (gint) cell->xpad * 2 + TOGGLE_WIDTH;
232   calc_height = (gint) cell->ypad * 2 + TOGGLE_WIDTH;
233
234   if (width)
235     *width = calc_width;
236
237   if (height)
238     *height = calc_height;
239
240   if (cell_area)
241     {
242       if (x_offset)
243         {
244           *x_offset = cell->xalign * (cell_area->width - calc_width - (2 * cell->xpad));
245           *x_offset = MAX (*x_offset, 0) + cell->xpad;
246         }
247       if (y_offset)
248         {
249           *y_offset = cell->yalign * (cell_area->height - calc_height - (2 * cell->ypad));
250           *y_offset = MAX (*y_offset, 0) + cell->ypad;
251         }
252     }
253 }
254
255 static void
256 gtk_cell_renderer_toggle_render (GtkCellRenderer *cell,
257                                  GdkWindow       *window,
258                                  GtkWidget       *widget,
259                                  GdkRectangle    *background_area,
260                                  GdkRectangle    *cell_area,
261                                  GdkRectangle    *expose_area,
262                                  guint            flags)
263 {
264   GtkCellRendererToggle *celltoggle = (GtkCellRendererToggle *) cell;
265   gint width, height;
266   gint x_offset, y_offset;
267   GtkShadowType shadow;
268   GtkStateType state;
269   
270   gtk_cell_renderer_toggle_get_size (cell, widget, cell_area,
271                                      &x_offset, &y_offset,
272                                      &width, &height);
273   width -= cell->xpad*2;
274   height -= cell->ypad*2;
275
276   if (width <= 0 || height <= 0)
277     return;
278
279   shadow = celltoggle->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
280
281   if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
282     state = GTK_STATE_SELECTED;
283   else if (! cell->can_activate)
284     state = GTK_STATE_INSENSITIVE;
285   else
286     state = GTK_STATE_NORMAL;
287   
288   if (celltoggle->radio)
289     {
290       gtk_paint_option (widget->style,
291                         window,
292                         state, shadow,
293                         cell_area, widget, "cellradio",
294                         cell_area->x + x_offset,
295                         cell_area->y + y_offset,
296                         width, height);
297     }
298   else
299     {
300       gtk_paint_check (widget->style,
301                        window,
302                        state, shadow,
303                        cell_area, widget, "cellcheck",
304                        cell_area->x + x_offset,
305                        cell_area->y + y_offset,
306                        width, height);
307     }
308 }
309
310 static gint
311 gtk_cell_renderer_toggle_event (GtkCellRenderer *cell,
312                                 GdkEvent        *event,
313                                 GtkWidget       *widget,
314                                 gchar           *path,
315                                 GdkRectangle    *background_area,
316                                 GdkRectangle    *cell_area,
317                                 guint            flags)
318 {
319   GtkCellRendererToggle *celltoggle;
320   gint retval = FALSE;
321   
322   celltoggle = GTK_CELL_RENDERER_TOGGLE (cell);
323   
324   switch (event->type)
325     {
326     case GDK_BUTTON_PRESS:
327       {
328         gtk_signal_emit (GTK_OBJECT (cell), toggle_cell_signals[TOGGLED], path);
329         retval = TRUE;
330       }
331       break;
332
333     default:
334       break;
335     }
336       
337   return retval;
338 }
339
340 /**
341  * gtk_cell_renderer_toggle_set_radio:
342  * @toggle: a #GtkCellRendererToggle
343  * @radio: %TRUE to make the toggle look like a radio button
344  * 
345  * If @radio is %TRUE, the cell renderer renders a radio toggle
346  * (i.e. a toggle in a group of mutually-exclusive toggles).
347  * If %FALSE, it renders a check toggle (a standalone boolean option).
348  * This can be set globally for the cell renderer, or changed just
349  * before rendering each cell in the model (for #GtkTreeView, you set
350  * up a per-row setting using #GtkTreeViewColumn to associate model
351  * columns with cell renderer properties).
352  **/
353 void
354 gtk_cell_renderer_toggle_set_radio (GtkCellRendererToggle *toggle,
355                                     gboolean               radio)
356 {
357   g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle));
358
359   toggle->radio = radio;
360 }
361
362 /**
363  * gtk_cell_renderer_toggle_get_radio:
364  * @toggle: a #GtkCellRendererToggle
365  * 
366  * Return value: %TRUE if we're rendering radio toggles rather than checkboxes
367  **/
368 gboolean
369 gtk_cell_renderer_toggle_get_radio (GtkCellRendererToggle *toggle)
370 {
371   g_return_val_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle), FALSE);
372
373   return toggle->radio;
374 }
375
376 gboolean
377 gtk_cell_renderer_toggle_get_active (GtkCellRendererToggle *toggle)
378 {
379   g_return_val_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle), FALSE);
380
381   return toggle->active;
382 }
383
384 void
385 gtk_cell_renderer_toggle_set_active (GtkCellRendererToggle *toggle,
386                                      gboolean               setting)
387 {
388   g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle));
389
390   g_object_set (G_OBJECT (toggle), "active", !! setting, NULL);
391 }