Make HildonCheckButton derive from GtkToggleButton
[hildon] / hildon / hildon-check-button.c
1 /*
2  * This file is a part of hildon
3  *
4  * Copyright (C) 2008 Nokia Corporation, all rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser Public License as published by
8  * the Free Software Foundation; version 2 of the license.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser Public License for more details.
14  *
15  */
16
17 /**
18  * SECTION:hildon-check-button
19  * @short_description: Button with a check box inside
20  *
21  * #HildonCheckButton is a button containing a label and a check box
22  * which will remain 'pressed-in' when clicked. Clicking again will
23  * make the check box toggle its state.
24  *
25  * #HildonCheckButton is similar to the #GtkCheckButton widget, but
26  * with a different appearance that combines a standard button and a
27  * check box.
28  *
29  * #HildonCheckButton derives from #GtkToggleButton so its state can
30  * be set with gtk_toggle_button_set_active(), and retrieved using
31  * gtk_toggle_button_get_active(). The label can be set using
32  * gtk_button_set_label() and retrieved using gtk_button_get_label().
33  *
34  * <note>
35  *   <para>
36  * #HildonCheckButton does NOT support an image, so don't use
37  * gtk_button_set_image().
38  *   </para>
39  * </note>
40  *
41  * <example>
42  * <title>Using a Hildon check button</title>
43  * <programlisting>
44  * void
45  * button_toggled (GtkToggleButton *button, gpointer user_data)
46  * {
47  *     gboolean active;
48  * <!-- -->
49  *     active = gtk_toggle_button_get_active (button);
50  *     if (active)
51  *        g_debug ("Button is active");
52  *     else
53  *        g_debug ("Button is not active");
54  * }
55  * <!-- -->
56  * GtkWidget *
57  * create_button (void)
58  * {
59  *     GtkWidget *button;
60  * <!-- -->
61  *     button = hildon_check_button_new (HILDON_SIZE_AUTO);
62  *     gtk_button_set_label (GTK_BUTTON (button), "Click me");
63  * <!-- -->
64  *     g_signal_connect (button, "toggled", G_CALLBACK (button_toggled), NULL);
65  * <!-- -->
66  *     return button;
67  * }
68  * </programlisting>
69  * </example>
70  */
71
72 #undef                                          HILDON_DISABLE_DEPRECATED
73
74 #include                                        "hildon-check-button.h"
75
76 enum {
77     PROP_SIZE = 1
78 };
79
80 G_DEFINE_TYPE                                   (HildonCheckButton, hildon_check_button, GTK_TYPE_TOGGLE_BUTTON);
81
82 #define                                         HILDON_CHECK_BUTTON_GET_PRIVATE(obj) \
83                                                 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
84                                                 HILDON_TYPE_CHECK_BUTTON, HildonCheckButtonPrivate));
85
86 struct                                          _HildonCheckButtonPrivate
87 {
88     GtkCellRendererToggle *toggle_renderer;
89 };
90
91 /**
92  * hildon_check_button_toggled:
93  * @button: A #HildonCheckButton
94  *
95  * Emits the #HildonCheckButton::toggled signal on the #HildonCheckButton.
96  *
97  * Deprecated: use gtk_toggle_button_toggled()
98  *
99  * Since: 2.2
100  */
101 void
102 hildon_check_button_toggled                     (HildonCheckButton *button)
103 {
104     g_return_if_fail (HILDON_IS_CHECK_BUTTON (button));
105
106     gtk_toggle_button_toggled (GTK_TOGGLE_BUTTON (button));
107 }
108
109 /**
110  * hildon_check_button_set_active:
111  * @button: A #HildonCheckButton
112  * @is_active: new state for the button
113  *
114  * Sets the status of a #HildonCheckButton.
115  *
116  * Deprecated: use gtk_toggle_button_set_active()
117  *
118  * Since: 2.2
119  **/
120 void
121 hildon_check_button_set_active                  (HildonCheckButton *button,
122                                                  gboolean           is_active)
123 {
124     g_return_if_fail (HILDON_IS_CHECK_BUTTON (button));
125
126     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), is_active);
127 }
128
129 /**
130  * hildon_check_button_get_active:
131  * @button: A #HildonCheckButton
132  *
133  * Gets the current state of @button.
134  *
135  * Return value: %TRUE if @button is active, %FALSE otherwise.
136  *
137  * Deprecated: use gtk_toggle_button_get_active()
138  *
139  * Since: 2.2
140  **/
141 gboolean
142 hildon_check_button_get_active                  (HildonCheckButton *button)
143 {
144     g_return_val_if_fail (HILDON_IS_CHECK_BUTTON (button), FALSE);
145
146     return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
147 }
148
149 /**
150  * hildon_check_button_new:
151  * @size: Flags indicating the size of the new button
152  *
153  * Creates a new #HildonCheckButton.
154  *
155  * Return value: A newly created #HildonCheckButton
156  *
157  * Since: 2.2
158  **/
159 GtkWidget *
160 hildon_check_button_new                         (HildonSizeType size)
161 {
162     return g_object_new (HILDON_TYPE_CHECK_BUTTON, "xalign", 0.0, "size", size, NULL);
163 }
164
165 static void
166 hildon_check_button_clicked                     (GtkButton *button)
167 {
168     HildonCheckButton *checkbutton = HILDON_CHECK_BUTTON (button);
169     GtkToggleButton *togglebutton = GTK_TOGGLE_BUTTON (button);
170
171     togglebutton->active = !togglebutton->active;
172     gtk_cell_renderer_toggle_set_active (checkbutton->priv->toggle_renderer,
173                                          togglebutton->active);
174
175     gtk_toggle_button_toggled (togglebutton);
176
177     gtk_widget_queue_draw (GTK_WIDGET (button));
178
179     g_object_notify (G_OBJECT (button), "active");
180 }
181
182 static void
183 hildon_check_button_apply_style                 (GtkWidget *widget)
184 {
185     guint checkbox_size;
186     HildonCheckButtonPrivate *priv = HILDON_CHECK_BUTTON (widget)->priv;
187
188     gtk_widget_style_get (widget, "checkbox-size", &checkbox_size, NULL);
189
190     g_object_set (priv->toggle_renderer, "indicator-size", checkbox_size, NULL);
191 }
192
193 static void
194 hildon_check_button_style_set                   (GtkWidget *widget,
195                                                  GtkStyle  *previous_style)
196 {
197     if (GTK_WIDGET_CLASS (hildon_check_button_parent_class)->style_set)
198         GTK_WIDGET_CLASS (hildon_check_button_parent_class)->style_set (widget, previous_style);
199
200     hildon_check_button_apply_style (widget);
201 }
202
203 static void
204 set_property                                    (GObject      *object,
205                                                  guint         prop_id,
206                                                  const GValue *value,
207                                                  GParamSpec   *pspec)
208 {
209     switch (prop_id)
210     {
211     case PROP_SIZE:
212         hildon_gtk_widget_set_theme_size (GTK_WIDGET (object), g_value_get_flags (value));
213         break;
214     default:
215         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
216         break;
217     }
218 }
219
220 static void
221 hildon_check_button_class_init                  (HildonCheckButtonClass *klass)
222 {
223     GObjectClass *gobject_class = (GObjectClass*) klass;
224     GtkWidgetClass *widget_class = (GtkWidgetClass*) klass;
225     GtkButtonClass *button_class = (GtkButtonClass*) klass;
226     GtkButtonClass *gtk_button_class = g_type_class_peek_parent (hildon_check_button_parent_class);
227
228     gobject_class->set_property = set_property;
229     widget_class->style_set = hildon_check_button_style_set;
230     button_class->clicked = hildon_check_button_clicked;
231     button_class->pressed = gtk_button_class->pressed;
232     button_class->released = gtk_button_class->released;
233     button_class->enter = gtk_button_class->enter;
234     button_class->leave = gtk_button_class->leave;
235
236     gtk_widget_class_install_style_property (
237         widget_class,
238         g_param_spec_uint (
239             "checkbox-size",
240             "Size of the check box",
241             "Size of the check box",
242             0, G_MAXUINT, 26,
243             G_PARAM_READABLE));
244
245     g_object_class_install_property (
246         gobject_class,
247         PROP_SIZE,
248         g_param_spec_flags (
249             "size",
250             "Size",
251             "Size request for the button",
252             HILDON_TYPE_SIZE_TYPE,
253             HILDON_SIZE_AUTO,
254             G_PARAM_WRITABLE));
255
256     g_type_class_add_private (klass, sizeof (HildonCheckButtonPrivate));
257 }
258
259 static void
260 hildon_check_button_init                        (HildonCheckButton *button)
261 {
262     HildonCheckButtonPrivate *priv = HILDON_CHECK_BUTTON_GET_PRIVATE (button);
263     GtkWidget *cell_view = gtk_cell_view_new ();
264
265     /* Store private part */
266     button->priv = priv;
267
268     /* Make sure that the check box is always shown, no matter the value of gtk-button-images */
269     g_signal_connect (cell_view, "notify::visible", G_CALLBACK (gtk_widget_show), NULL);
270
271     /* Create toggle renderer and pack it into the cell view */
272     priv->toggle_renderer = GTK_CELL_RENDERER_TOGGLE (gtk_cell_renderer_toggle_new ());
273     gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cell_view),
274                                 GTK_CELL_RENDERER (priv->toggle_renderer), FALSE);
275
276     /* Add cell view to the image */
277     gtk_button_set_image (GTK_BUTTON (button), cell_view);
278
279     gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
280
281     hildon_check_button_apply_style (GTK_WIDGET (button));
282 }