gtkcellrenderertoggle.c 10.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* gtkcellrenderertoggle.c
 * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <stdlib.h>
#include <gtk/gtkcellrenderertoggle.h>
#include <gtk/gtksignal.h>
Havoc Pennington's avatar
Havoc Pennington committed
23
#include "gtkintl.h"
24

25
26
27
28
29
30
31
32
33
34
static void gtk_cell_renderer_toggle_get_property  (GObject                    *object,
						    guint                       param_id,
						    GValue                     *value,
						    GParamSpec                 *pspec,
						    const gchar                *trailer);
static void gtk_cell_renderer_toggle_set_property  (GObject                    *object,
						    guint                       param_id,
						    const GValue               *value,
						    GParamSpec                 *pspec,
						    const gchar                *trailer);
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
static void gtk_cell_renderer_toggle_init       (GtkCellRendererToggle      *celltext);
static void gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class);
static void gtk_cell_renderer_toggle_get_size   (GtkCellRenderer            *cell,
						 GtkWidget                  *widget,
						 gint                       *width,
						 gint                       *height);
static void gtk_cell_renderer_toggle_render     (GtkCellRenderer            *cell,
						 GdkWindow                  *window,
						 GtkWidget                  *widget,
						 GdkRectangle               *background_area,
						 GdkRectangle               *cell_area,
						 GdkRectangle               *expose_area,
						 guint                       flags);
static gint gtk_cell_renderer_toggle_event      (GtkCellRenderer            *cell,
						 GdkEvent                   *event,
						 GtkWidget                  *widget,
						 gchar                      *path,
						 GdkRectangle               *background_area,
						 GdkRectangle               *cell_area,
						 guint                       flags);


enum {
  TOGGLED,
  LAST_SIGNAL
};

enum {
  PROP_ZERO,
Havoc Pennington's avatar
Havoc Pennington committed
64
  PROP_ACTIVE,
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
  PROP_RADIO
};


#define TOGGLE_WIDTH 12

static guint toggle_cell_signals[LAST_SIGNAL] = { 0 };


GtkType
gtk_cell_renderer_toggle_get_type (void)
{
  static GtkType cell_toggle_type = 0;

  if (!cell_toggle_type)
    {
      static const GTypeInfo cell_toggle_info =
      {
	sizeof (GtkCellRendererToggleClass),
	NULL,		/* base_init */
	NULL,		/* base_finalize */
	(GClassInitFunc) gtk_cell_renderer_toggle_class_init,
	NULL,		/* class_finalize */
	NULL,		/* class_data */
	sizeof (GtkCellRendererToggle),
	0,              /* n_preallocs */
	(GInstanceInitFunc) gtk_cell_renderer_toggle_init,
      };

94
      cell_toggle_type = g_type_register_static (GTK_TYPE_CELL_RENDERER, "GtkCellRendererToggle", &cell_toggle_info, 0);
95
96
97
98
99
100
101
102
    }

  return cell_toggle_type;
}

static void
gtk_cell_renderer_toggle_init (GtkCellRendererToggle *celltoggle)
{
Havoc Pennington's avatar
Havoc Pennington committed
103
  celltoggle->active = FALSE;
104
105
106
107
108
109
110
111
112
113
114
  celltoggle->radio = FALSE;
  GTK_CELL_RENDERER (celltoggle)->xpad = 2;
  GTK_CELL_RENDERER (celltoggle)->ypad = 2;
}

static void
gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class)
{
  GObjectClass *object_class = G_OBJECT_CLASS (class);
  GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);

115
116
  object_class->get_property = gtk_cell_renderer_toggle_get_property;
  object_class->set_property = gtk_cell_renderer_toggle_set_property;
117
118
119
120

  cell_class->get_size = gtk_cell_renderer_toggle_get_size;
  cell_class->render = gtk_cell_renderer_toggle_render;
  cell_class->event = gtk_cell_renderer_toggle_event;
121
122
  
  g_object_class_install_property (object_class,
Havoc Pennington's avatar
Havoc Pennington committed
123
124
				   PROP_ACTIVE,
				   g_param_spec_boolean ("active",
125
							 _("Toggle state"),
Havoc Pennington's avatar
Havoc Pennington committed
126
							 _("The toggle state of the button"),
127
128
129
130
131
132
133
134
							 FALSE,
							 G_PARAM_READABLE |
							 G_PARAM_WRITABLE));
  
  g_object_class_install_property (object_class,
				   PROP_RADIO,
				   g_param_spec_boolean ("radio",
							 _("Radio state"),
Havoc Pennington's avatar
Havoc Pennington committed
135
							 _("Draw the toggle button as a radio button"),
136
137
138
							 FALSE,
							 G_PARAM_READABLE |
							 G_PARAM_WRITABLE));
139
140
141
142
143
144
145


  toggle_cell_signals[TOGGLED] =
    gtk_signal_new ("toggled",
		    GTK_RUN_LAST,
		    GTK_CLASS_TYPE (object_class),
		    GTK_SIGNAL_OFFSET (GtkCellRendererToggleClass, toggled),
146
		    gtk_marshal_VOID__POINTER,
147
148
149
150
151
		    GTK_TYPE_NONE, 1,
		    GTK_TYPE_POINTER);
}

static void
152
153
154
155
156
gtk_cell_renderer_toggle_get_property (GObject     *object,
				       guint        param_id,
				       GValue      *value,
				       GParamSpec  *pspec,
				       const gchar *trailer)
157
158
{
  GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (object);
159
  
160
161
  switch (param_id)
    {
Havoc Pennington's avatar
Havoc Pennington committed
162
163
    case PROP_ACTIVE:
      g_value_set_boolean (value, celltoggle->active);
164
165
166
167
168
      break;
    case PROP_RADIO:
      g_value_set_boolean (value, celltoggle->radio);
      break;
    default:
169
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
170
171
172
173
174
175
      break;
    }
}


static void
176
177
178
179
180
gtk_cell_renderer_toggle_set_property (GObject      *object,
				       guint         param_id,
				       const GValue *value,
				       GParamSpec   *pspec,
				       const gchar  *trailer)
181
182
{
  GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (object);
183
  
184
185
  switch (param_id)
    {
Havoc Pennington's avatar
Havoc Pennington committed
186
    case PROP_ACTIVE:
187
      celltoggle->active = g_value_get_boolean (value);
188
189
190
191
192
      break;
    case PROP_RADIO:
      celltoggle->radio = g_value_get_boolean (value);
      break;
    default:
193
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
194
195
196
197
      break;
    }
}

198
199
200
201
202
203
204
205
206
207
208
209
210
/**
 * gtk_cell_renderer_toggle_new:
 * 
 * Creates a new #GtkCellRendererToggle. Adjust rendering
 * parameters using object properties. Object properties can be set
 * globally (with g_object_set()). Also, with #GtkTreeViewColumn, you
 * can bind a property to a value in a #GtkTreeModel. For example, you
 * can bind the "active" property on the cell renderer to a boolean value
 * in the model, thus causing the check button to reflect the state of
 * the model.
 * 
 * Return value: the new cell renderer
 **/
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
GtkCellRenderer *
gtk_cell_renderer_toggle_new (void)
{
  return GTK_CELL_RENDERER (gtk_type_new (gtk_cell_renderer_toggle_get_type ()));
}

static void
gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell,
				   GtkWidget       *widget,
				   gint            *width,
				   gint            *height)
{
  if (width)
    *width = (gint) cell->xpad * 2 + TOGGLE_WIDTH;

  if (height)
    *height = (gint) cell->ypad * 2 + TOGGLE_WIDTH;
}

static void
gtk_cell_renderer_toggle_render (GtkCellRenderer *cell,
				 GdkWindow       *window,
				 GtkWidget       *widget,
				 GdkRectangle    *background_area,
				 GdkRectangle    *cell_area,
				 GdkRectangle    *expose_area,
				 guint            flags)
{
  GtkCellRendererToggle *celltoggle = (GtkCellRendererToggle *) cell;
  gint width, height;
  gint real_xoffset, real_yoffset;
Havoc Pennington's avatar
Havoc Pennington committed
242
243
244
  GtkShadowType shadow;
  GtkStateType state;
  
245
246
247
248
249
250
251
252
253
254
255
  width = MIN (TOGGLE_WIDTH, cell_area->width - cell->xpad * 2);
  height = MIN (TOGGLE_WIDTH, cell_area->height - cell->ypad * 2);

  if (width <= 0 || height <= 0)
    return;

  real_xoffset = cell->xalign * (cell_area->width - width - (2 * cell->xpad));
  real_xoffset = MAX (real_xoffset, 0) + cell->xpad;
  real_yoffset = cell->yalign * (cell_area->height - height - (2 * cell->ypad));
  real_yoffset = MAX (real_yoffset, 0) + cell->ypad;

Havoc Pennington's avatar
Havoc Pennington committed
256
  shadow = celltoggle->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
257

Havoc Pennington's avatar
Havoc Pennington committed
258
259
260
261
262
263
  if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
    state = GTK_STATE_SELECTED;
  else
    state = GTK_STATE_NORMAL;
  
  if (celltoggle->radio)
264
    {
Havoc Pennington's avatar
Havoc Pennington committed
265
266
267
268
269
270
271
      gtk_paint_option (widget->style,
                        window,
                        state, shadow,
                        cell_area, widget, "cellradio",
                        cell_area->x + real_xoffset,
                        cell_area->y + real_yoffset,
                        width, height);
272
273
274
    }
  else
    {
Havoc Pennington's avatar
Havoc Pennington committed
275
276
277
278
279
280
281
      gtk_paint_check (widget->style,
                       window,
                       state, shadow,
                       cell_area, widget, "cellcheck",
                       cell_area->x + real_xoffset,
                       cell_area->y + real_yoffset,
                       width, height);
282
283
284
285
286
287
288
289
290
291
292
293
    }
}

static gint
gtk_cell_renderer_toggle_event (GtkCellRenderer *cell,
				GdkEvent        *event,
				GtkWidget       *widget,
				gchar           *path,
				GdkRectangle    *background_area,
				GdkRectangle    *cell_area,
				guint            flags)
{
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
  GtkCellRendererToggle *celltoggle;
  gint retval = FALSE;
  
  celltoggle = GTK_CELL_RENDERER_TOGGLE (cell);
  
  switch (event->type)
    {
    case GDK_BUTTON_PRESS:
      {
        gtk_signal_emit (GTK_OBJECT (cell), toggle_cell_signals[TOGGLED], path);
        retval = TRUE;
      }
      break;

    default:
      break;
    }
      
  return retval;
313
314
}

315
316
317
318
319
320
321
322
323
324
325
326
327
/**
 * gtk_cell_renderer_toggle_set_radio:
 * @toggle: a #GtkCellRendererToggle
 * @radio: %TRUE to make the toggle look like a radio button
 * 
 * If @radio is %TRUE, the cell renderer renders a radio toggle
 * (i.e. a toggle in a group of mutually-exclusive toggles).
 * If %FALSE, it renders a check toggle (a standalone boolean option).
 * This can be set globally for the cell renderer, or changed just
 * before rendering each cell in the model (for #GtkTreeView, you set
 * up a per-row setting using #GtkTreeViewColumn to associate model
 * columns with cell renderer properties).
 **/
328
329
330
331
332
333
334
335
void
gtk_cell_renderer_toggle_set_radio (GtkCellRendererToggle *toggle,
				    gboolean               radio)
{
  g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle));

  toggle->radio = radio;
}
Havoc Pennington's avatar
Havoc Pennington committed
336

337
338
339
340
341
342
/**
 * gtk_cell_renderer_toggle_get_radio:
 * @toggle: a #GtkCellRendererToggle
 * 
 * Return value: %TRUE if we're rendering radio toggles rather than checkboxes
 **/
Havoc Pennington's avatar
Havoc Pennington committed
343
gboolean
344
gtk_cell_renderer_toggle_get_radio (GtkCellRendererToggle *toggle)
Havoc Pennington's avatar
Havoc Pennington committed
345
346
347
{
  g_return_val_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle), FALSE);

348
  return toggle->radio;
Havoc Pennington's avatar
Havoc Pennington committed
349
}
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364

gboolean
gtk_cell_renderer_toggle_get_active (GtkCellRendererToggle *toggle)
{
  g_return_val_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle), FALSE);

  return toggle->active;
}

void
gtk_cell_renderer_toggle_set_active (GtkCellRendererToggle *toggle,
				     gboolean               setting)
{
  g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle));

365
  g_object_set (G_OBJECT (toggle), "active", !! setting, NULL);
366
}