]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellrenderertoggle.c
Intern some more strings.
[~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 <config.h>
21 #include <stdlib.h>
22 #include "gtkcellrenderertoggle.h"
23 #include "gtkintl.h"
24 #include "gtkmarshalers.h"
25 #include "gtkprivate.h"
26 #include "gtktreeprivate.h"
27 #include "gtkalias.h"
28
29 static void gtk_cell_renderer_toggle_get_property  (GObject                    *object,
30                                                     guint                       param_id,
31                                                     GValue                     *value,
32                                                     GParamSpec                 *pspec);
33 static void gtk_cell_renderer_toggle_set_property  (GObject                    *object,
34                                                     guint                       param_id,
35                                                     const GValue               *value,
36                                                     GParamSpec                 *pspec);
37 static void gtk_cell_renderer_toggle_init       (GtkCellRendererToggle      *celltext);
38 static void gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class);
39 static void gtk_cell_renderer_toggle_get_size   (GtkCellRenderer            *cell,
40                                                  GtkWidget                  *widget,
41                                                  GdkRectangle               *cell_area,
42                                                  gint                       *x_offset,
43                                                  gint                       *y_offset,
44                                                  gint                       *width,
45                                                  gint                       *height);
46 static void gtk_cell_renderer_toggle_render     (GtkCellRenderer            *cell,
47                                                  GdkWindow                  *window,
48                                                  GtkWidget                  *widget,
49                                                  GdkRectangle               *background_area,
50                                                  GdkRectangle               *cell_area,
51                                                  GdkRectangle               *expose_area,
52                                                  GtkCellRendererState        flags);
53 static gboolean gtk_cell_renderer_toggle_activate  (GtkCellRenderer            *cell,
54                                                     GdkEvent                   *event,
55                                                     GtkWidget                  *widget,
56                                                     const gchar                *path,
57                                                     GdkRectangle               *background_area,
58                                                     GdkRectangle               *cell_area,
59                                                     GtkCellRendererState        flags);
60
61
62 enum {
63   TOGGLED,
64   LAST_SIGNAL
65 };
66
67 enum {
68   PROP_ZERO,
69   PROP_ACTIVATABLE,
70   PROP_ACTIVE,
71   PROP_RADIO,
72   PROP_INCONSISTENT
73 };
74
75 #define TOGGLE_WIDTH 12
76
77 static guint toggle_cell_signals[LAST_SIGNAL] = { 0 };
78
79 #define GTK_CELL_RENDERER_TOGGLE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_CELL_RENDERER_TOGGLE, GtkCellRendererTogglePrivate))
80
81 typedef struct _GtkCellRendererTogglePrivate GtkCellRendererTogglePrivate;
82 struct _GtkCellRendererTogglePrivate
83 {
84   guint inconsistent : 1;
85 };
86
87
88 GType
89 gtk_cell_renderer_toggle_get_type (void)
90 {
91   static GType cell_toggle_type = 0;
92
93   if (!cell_toggle_type)
94     {
95       static const GTypeInfo cell_toggle_info =
96       {
97         sizeof (GtkCellRendererToggleClass),
98         NULL,           /* base_init */
99         NULL,           /* base_finalize */
100         (GClassInitFunc) gtk_cell_renderer_toggle_class_init,
101         NULL,           /* class_finalize */
102         NULL,           /* class_data */
103         sizeof (GtkCellRendererToggle),
104         0,              /* n_preallocs */
105         (GInstanceInitFunc) gtk_cell_renderer_toggle_init,
106       };
107
108       cell_toggle_type =
109         g_type_register_static (GTK_TYPE_CELL_RENDERER, I_("GtkCellRendererToggle"),
110                                 &cell_toggle_info, 0);
111     }
112
113   return cell_toggle_type;
114 }
115
116 static void
117 gtk_cell_renderer_toggle_init (GtkCellRendererToggle *celltoggle)
118 {
119   celltoggle->activatable = TRUE;
120   celltoggle->active = FALSE;
121   celltoggle->radio = FALSE;
122   GTK_CELL_RENDERER (celltoggle)->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE;
123   GTK_CELL_RENDERER (celltoggle)->xpad = 2;
124   GTK_CELL_RENDERER (celltoggle)->ypad = 2;
125 }
126
127 static void
128 gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class)
129 {
130   GObjectClass *object_class = G_OBJECT_CLASS (class);
131   GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
132
133   object_class->get_property = gtk_cell_renderer_toggle_get_property;
134   object_class->set_property = gtk_cell_renderer_toggle_set_property;
135
136   cell_class->get_size = gtk_cell_renderer_toggle_get_size;
137   cell_class->render = gtk_cell_renderer_toggle_render;
138   cell_class->activate = gtk_cell_renderer_toggle_activate;
139   
140   g_object_class_install_property (object_class,
141                                    PROP_ACTIVE,
142                                    g_param_spec_boolean ("active",
143                                                          P_("Toggle state"),
144                                                          P_("The toggle state of the button"),
145                                                          FALSE,
146                                                          GTK_PARAM_READWRITE));
147
148   g_object_class_install_property (object_class,
149                                    PROP_INCONSISTENT,
150                                    g_param_spec_boolean ("inconsistent",
151                                                          P_("Inconsistent state"),
152                                                          P_("The inconsistent state of the button"),
153                                                          FALSE,
154                                                          GTK_PARAM_READWRITE));
155   
156   g_object_class_install_property (object_class,
157                                    PROP_ACTIVATABLE,
158                                    g_param_spec_boolean ("activatable",
159                                                          P_("Activatable"),
160                                                          P_("The toggle button can be activated"),
161                                                          TRUE,
162                                                          GTK_PARAM_READWRITE));
163
164   g_object_class_install_property (object_class,
165                                    PROP_RADIO,
166                                    g_param_spec_boolean ("radio",
167                                                          P_("Radio state"),
168                                                          P_("Draw the toggle button as a radio button"),
169                                                          FALSE,
170                                                          GTK_PARAM_READWRITE));
171
172   
173   /**
174    * GtkCellRendererToggle::toggled:
175    * @cell_renderer: the object which received the signal
176    * @path: string representation of #GtkTreePath describing the 
177    *        event location
178    *
179    * The ::toggled signal is emitted when the cell is toggled. 
180    **/
181   toggle_cell_signals[TOGGLED] =
182     g_signal_new (I_("toggled"),
183                   G_OBJECT_CLASS_TYPE (object_class),
184                   G_SIGNAL_RUN_LAST,
185                   G_STRUCT_OFFSET (GtkCellRendererToggleClass, toggled),
186                   NULL, NULL,
187                   _gtk_marshal_VOID__STRING,
188                   G_TYPE_NONE, 1,
189                   G_TYPE_STRING);
190
191   g_type_class_add_private (object_class, sizeof (GtkCellRendererTogglePrivate));
192 }
193
194 static void
195 gtk_cell_renderer_toggle_get_property (GObject     *object,
196                                        guint        param_id,
197                                        GValue      *value,
198                                        GParamSpec  *pspec)
199 {
200   GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (object);
201   GtkCellRendererTogglePrivate *priv;
202
203   priv = GTK_CELL_RENDERER_TOGGLE_GET_PRIVATE (object);
204   
205   switch (param_id)
206     {
207     case PROP_ACTIVE:
208       g_value_set_boolean (value, celltoggle->active);
209       break;
210     case PROP_INCONSISTENT:
211       g_value_set_boolean (value, priv->inconsistent);
212       break;
213     case PROP_ACTIVATABLE:
214       g_value_set_boolean (value, celltoggle->activatable);
215       break;
216     case PROP_RADIO:
217       g_value_set_boolean (value, celltoggle->radio);
218       break;
219     default:
220       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
221       break;
222     }
223 }
224
225
226 static void
227 gtk_cell_renderer_toggle_set_property (GObject      *object,
228                                        guint         param_id,
229                                        const GValue *value,
230                                        GParamSpec   *pspec)
231 {
232   GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (object);
233   GtkCellRendererTogglePrivate *priv;
234
235   priv = GTK_CELL_RENDERER_TOGGLE_GET_PRIVATE (object);
236   
237   switch (param_id)
238     {
239     case PROP_ACTIVE:
240       celltoggle->active = g_value_get_boolean (value);
241       g_object_notify (G_OBJECT(object), "active");
242       break;
243     case PROP_INCONSISTENT:
244       priv->inconsistent = g_value_get_boolean (value);
245       g_object_notify (G_OBJECT (object), "inconsistent");
246       break;
247     case PROP_ACTIVATABLE:
248       celltoggle->activatable = g_value_get_boolean (value);
249       g_object_notify (G_OBJECT(object), "activatable");
250       break;
251     case PROP_RADIO:
252       celltoggle->radio = g_value_get_boolean (value);
253       g_object_notify (G_OBJECT(object), "radio");
254       break;
255     default:
256       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
257       break;
258     }
259 }
260
261 /**
262  * gtk_cell_renderer_toggle_new:
263  * 
264  * Creates a new #GtkCellRendererToggle. Adjust rendering
265  * parameters using object properties. Object properties can be set
266  * globally (with g_object_set()). Also, with #GtkTreeViewColumn, you
267  * can bind a property to a value in a #GtkTreeModel. For example, you
268  * can bind the "active" property on the cell renderer to a boolean value
269  * in the model, thus causing the check button to reflect the state of
270  * the model.
271  * 
272  * Return value: the new cell renderer
273  **/
274 GtkCellRenderer *
275 gtk_cell_renderer_toggle_new (void)
276 {
277   return g_object_new (GTK_TYPE_CELL_RENDERER_TOGGLE, NULL);
278 }
279
280 static void
281 gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell,
282                                    GtkWidget       *widget,
283                                    GdkRectangle    *cell_area,
284                                    gint            *x_offset,
285                                    gint            *y_offset,
286                                    gint            *width,
287                                    gint            *height)
288 {
289   gint calc_width;
290   gint calc_height;
291
292   calc_width = (gint) cell->xpad * 2 + TOGGLE_WIDTH;
293   calc_height = (gint) cell->ypad * 2 + TOGGLE_WIDTH;
294
295   if (width)
296     *width = calc_width;
297
298   if (height)
299     *height = calc_height;
300
301   if (cell_area)
302     {
303       if (x_offset)
304         {
305           *x_offset = ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ?
306                        (1.0 - cell->xalign) : cell->xalign) * (cell_area->width - calc_width);
307           *x_offset = MAX (*x_offset, 0);
308         }
309       if (y_offset)
310         {
311           *y_offset = cell->yalign * (cell_area->height - calc_height);
312           *y_offset = MAX (*y_offset, 0);
313         }
314     }
315 }
316
317 static void
318 gtk_cell_renderer_toggle_render (GtkCellRenderer      *cell,
319                                  GdkDrawable          *window,
320                                  GtkWidget            *widget,
321                                  GdkRectangle         *background_area,
322                                  GdkRectangle         *cell_area,
323                                  GdkRectangle         *expose_area,
324                                  GtkCellRendererState  flags)
325 {
326   GtkCellRendererToggle *celltoggle = (GtkCellRendererToggle *) cell;
327   GtkCellRendererTogglePrivate *priv;
328   gint width, height;
329   gint x_offset, y_offset;
330   GtkShadowType shadow;
331   GtkStateType state = 0;
332
333   priv = GTK_CELL_RENDERER_TOGGLE_GET_PRIVATE (cell);
334
335   gtk_cell_renderer_toggle_get_size (cell, widget, cell_area,
336                                      &x_offset, &y_offset,
337                                      &width, &height);
338   width -= cell->xpad*2;
339   height -= cell->ypad*2;
340
341   if (width <= 0 || height <= 0)
342     return;
343
344   if (priv->inconsistent)
345     shadow = GTK_SHADOW_ETCHED_IN;
346   else
347     shadow = celltoggle->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
348
349   if (!cell->sensitive)
350     {
351       state = GTK_STATE_INSENSITIVE;
352     }
353   else if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
354     {
355       if (GTK_WIDGET_HAS_FOCUS (widget))
356         state = GTK_STATE_SELECTED;
357       else
358         state = GTK_STATE_ACTIVE;
359     }
360   else
361     {
362       if (celltoggle->activatable)
363         state = GTK_STATE_NORMAL;
364       else
365         state = GTK_STATE_INSENSITIVE;
366     }
367
368   if (celltoggle->radio)
369     {
370       gtk_paint_option (widget->style,
371                         window,
372                         state, shadow,
373                         expose_area, widget, "cellradio",
374                         cell_area->x + x_offset + cell->xpad,
375                         cell_area->y + y_offset + cell->ypad,
376                         width - 1, height - 1);
377     }
378   else
379     {
380       gtk_paint_check (widget->style,
381                        window,
382                        state, shadow,
383                        expose_area, widget, "cellcheck",
384                        cell_area->x + x_offset + cell->xpad,
385                        cell_area->y + y_offset + cell->ypad,
386                        width - 1, height - 1);
387     }
388 }
389
390 static gint
391 gtk_cell_renderer_toggle_activate (GtkCellRenderer      *cell,
392                                    GdkEvent             *event,
393                                    GtkWidget            *widget,
394                                    const gchar          *path,
395                                    GdkRectangle         *background_area,
396                                    GdkRectangle         *cell_area,
397                                    GtkCellRendererState  flags)
398 {
399   GtkCellRendererToggle *celltoggle;
400   
401   celltoggle = GTK_CELL_RENDERER_TOGGLE (cell);
402   if (celltoggle->activatable)
403     {
404       g_signal_emit (cell, toggle_cell_signals[TOGGLED], 0, path);
405       return TRUE;
406     }
407
408   return FALSE;
409 }
410
411 /**
412  * gtk_cell_renderer_toggle_set_radio:
413  * @toggle: a #GtkCellRendererToggle
414  * @radio: %TRUE to make the toggle look like a radio button
415  * 
416  * If @radio is %TRUE, the cell renderer renders a radio toggle
417  * (i.e. a toggle in a group of mutually-exclusive toggles).
418  * If %FALSE, it renders a check toggle (a standalone boolean option).
419  * This can be set globally for the cell renderer, or changed just
420  * before rendering each cell in the model (for #GtkTreeView, you set
421  * up a per-row setting using #GtkTreeViewColumn to associate model
422  * columns with cell renderer properties).
423  **/
424 void
425 gtk_cell_renderer_toggle_set_radio (GtkCellRendererToggle *toggle,
426                                     gboolean               radio)
427 {
428   g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle));
429
430   toggle->radio = radio;
431 }
432
433 /**
434  * gtk_cell_renderer_toggle_get_radio:
435  * @toggle: a #GtkCellRendererToggle
436  *
437  * Returns whether we're rendering radio toggles rather than checkboxes. 
438  * 
439  * Return value: %TRUE if we're rendering radio toggles rather than checkboxes
440  **/
441 gboolean
442 gtk_cell_renderer_toggle_get_radio (GtkCellRendererToggle *toggle)
443 {
444   g_return_val_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle), FALSE);
445
446   return toggle->radio;
447 }
448
449 /**
450  * gtk_cell_renderer_toggle_get_active:
451  * @toggle: a #GtkCellRendererToggle
452  *
453  * Returns whether the cell renderer is active. See
454  * gtk_cell_renderer_toggle_set_active().
455  *
456  * Return value: %TRUE if the cell renderer is active.
457  **/
458 gboolean
459 gtk_cell_renderer_toggle_get_active (GtkCellRendererToggle *toggle)
460 {
461   g_return_val_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle), FALSE);
462
463   return toggle->active;
464 }
465
466 /**
467  * gtk_cell_renderer_toggle_set_active:
468  * @toggle: a #GtkCellRendererToggle.
469  * @setting: the value to set.
470  *
471  * Activates or deactivates a cell renderer.
472  **/
473 void
474 gtk_cell_renderer_toggle_set_active (GtkCellRendererToggle *toggle,
475                                      gboolean               setting)
476 {
477   g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle));
478
479   g_object_set (toggle, "active", setting ? TRUE : FALSE, NULL);
480 }
481
482 #define __GTK_CELL_RENDERER_TOGGLE_C__
483 #include "gtkaliasdef.c"