Renamed src/ to hildon/
[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  * The state of a #HildonCheckButton can be set using
26  * hildon_check_button_set_active(), and retrieved using
27  * hildon_check_button_get_active(). The label can be set using
28  * gtk_button_set_label() and retrieved using gtk_button_get_label().
29  *
30  * <note>
31  *   <para>
32  * #HildonCheckButton does NOT support an image, so don't use
33  * gtk_button_set_image().
34  *   </para>
35  * </note>
36  *
37  * <example>
38  * <title>Using a Hildon check button</title>
39  * <programlisting>
40  * void
41  * button_toggled (HildonCheckButton *button, gpointer user_data)
42  * {
43  *     gboolean active;
44  * <!-- -->
45  *     active = hildon_check_button_get_active (button);
46  *     if (active)
47  *        g_debug ("Button is active");
48  *     else
49  *        g_debug ("Button is not active");
50  * }
51  * <!-- -->
52  * GtkWidget *
53  * create_button (void)
54  * {
55  *     GtkWidget *button;
56  * <!-- -->
57  *     button = hildon_check_button_new (HILDON_SIZE_AUTO);
58  *     gtk_button_set_label (GTK_BUTTON (button), "Click me");
59  * <!-- -->
60  *     g_signal_connect (button, "toggled", G_CALLBACK (button_toggled), NULL);
61  * <!-- -->
62  *     return button;
63  * }
64  * </programlisting>
65  * </example>
66  */
67
68 #include                                        "hildon-check-button.h"
69
70 enum {
71   TOGGLED,
72   LAST_SIGNAL
73 };
74
75 static guint                                    signals[LAST_SIGNAL] = { 0 };
76
77 G_DEFINE_TYPE                                   (HildonCheckButton, hildon_check_button, GTK_TYPE_BUTTON);
78
79 #define                                         HILDON_CHECK_BUTTON_GET_PRIVATE(obj) \
80                                                 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
81                                                 HILDON_TYPE_CHECK_BUTTON, HildonCheckButtonPrivate));
82
83 struct                                          _HildonCheckButtonPrivate
84 {
85     GtkCellRendererToggle *toggle_renderer;
86 };
87
88 /**
89  * hildon_check_button_toggled:
90  * @button: A #HildonCheckButton
91  *
92  * Emits the #HildonCheckButton::toggled signal on the #HildonCheckButton.
93  * There is no good reason for an application ever to call this function.
94  *
95  * Since: 2.2
96  */
97 void
98 hildon_check_button_toggled                     (HildonCheckButton *button)
99 {
100     g_return_if_fail (HILDON_IS_CHECK_BUTTON (button));
101
102     g_signal_emit (button, signals[TOGGLED], 0);
103 }
104
105 /**
106  * hildon_check_button_set_active:
107  * @button: A #HildonCheckButton
108  * @is_active: new state for the button
109  *
110  * Sets the status of a #HildonCheckButton. Set to %TRUE if you want
111  * @button to be 'pressed-in', and %FALSE to raise it. This action
112  * causes the #HildonCheckButton::toggled signal to be emitted.
113  *
114  * Since: 2.2
115  **/
116 void
117 hildon_check_button_set_active                  (HildonCheckButton *button,
118                                                  gboolean           is_active)
119 {
120     gboolean prev_is_active;
121
122     g_return_if_fail (HILDON_IS_CHECK_BUTTON (button));
123
124     prev_is_active = hildon_check_button_get_active (button);
125
126     if (prev_is_active != is_active) {
127         gtk_button_clicked (GTK_BUTTON (button));
128         gtk_widget_queue_draw (GTK_WIDGET (button));
129     }
130 }
131
132 /**
133  * hildon_check_button_get_active:
134  * @button: A #HildonCheckButton
135  *
136  * Gets the current state of @button.
137  *
138  * Return value: %TRUE if @button is active, %FALSE otherwise.
139  *
140  * Since: 2.2
141  **/
142 gboolean
143 hildon_check_button_get_active                  (HildonCheckButton *button)
144 {
145     g_return_val_if_fail (HILDON_IS_CHECK_BUTTON (button), FALSE);
146
147     return gtk_cell_renderer_toggle_get_active (button->priv->toggle_renderer);
148 }
149
150 /**
151  * hildon_check_button_new:
152  * @size: Flags indicating the size of the new button
153  *
154  * Creates a new #HildonCheckButton.
155  *
156  * Return value: A newly created #HildonCheckButton
157  *
158  * Since: 2.2
159  **/
160 GtkWidget *
161 hildon_check_button_new                         (HildonSizeType size)
162 {
163     GtkWidget *button = g_object_new (HILDON_TYPE_CHECK_BUTTON, "xalign", 0.0, NULL);
164     hildon_gtk_widget_set_theme_size (button, size);
165     return button;
166 }
167
168 static void
169 hildon_check_button_clicked                     (GtkButton *button)
170 {
171     HildonCheckButton *checkbutton = HILDON_CHECK_BUTTON (button);
172     gboolean current = hildon_check_button_get_active (checkbutton);
173
174     gtk_cell_renderer_toggle_set_active (checkbutton->priv->toggle_renderer, !current);
175
176     hildon_check_button_toggled (checkbutton);
177 }
178
179 static void
180 hildon_check_button_apply_style                 (GtkWidget *widget)
181 {
182     guint checkbox_size;
183     HildonCheckButtonPrivate *priv = HILDON_CHECK_BUTTON (widget)->priv;
184
185     gtk_widget_style_get (widget, "checkbox-size", &checkbox_size, NULL);
186
187     g_object_set (priv->toggle_renderer, "indicator-size", checkbox_size, NULL);
188 }
189
190 static void
191 hildon_check_button_style_set                   (GtkWidget *widget,
192                                                  GtkStyle  *previous_style)
193 {
194     if (GTK_WIDGET_CLASS (hildon_check_button_parent_class)->style_set)
195         GTK_WIDGET_CLASS (hildon_check_button_parent_class)->style_set (widget, previous_style);
196
197     hildon_check_button_apply_style (widget);
198 }
199
200 static void
201 hildon_check_button_class_init                  (HildonCheckButtonClass *klass)
202 {
203     GObjectClass *gobject_class = (GObjectClass*) klass;
204     GtkWidgetClass *widget_class = (GtkWidgetClass*) klass;
205     GtkButtonClass *button_class = (GtkButtonClass*) klass;
206
207     widget_class->style_set = hildon_check_button_style_set;
208     button_class->clicked = hildon_check_button_clicked;
209
210     klass->toggled = NULL;
211
212     /**
213      * HildonCheckButton::toggled
214      *
215      * Emitted when the #HildonCheckButton's state is changed.
216      *
217      * Since: 2.2
218      */
219     signals[TOGGLED] =
220         g_signal_new ("toggled",
221                       G_OBJECT_CLASS_TYPE (gobject_class),
222                       G_SIGNAL_RUN_FIRST,
223                       G_STRUCT_OFFSET (HildonCheckButtonClass, toggled),
224                       NULL, NULL,
225                       g_cclosure_marshal_VOID__VOID,
226                       G_TYPE_NONE, 0);
227
228     gtk_widget_class_install_style_property (
229         widget_class,
230         g_param_spec_uint (
231             "checkbox-size",
232             "Size of the check box",
233             "Size of the check box",
234             0, G_MAXUINT, 26,
235             G_PARAM_READABLE));
236
237     g_type_class_add_private (klass, sizeof (HildonCheckButtonPrivate));
238 }
239
240 static void
241 hildon_check_button_init                        (HildonCheckButton *button)
242 {
243     HildonCheckButtonPrivate *priv = HILDON_CHECK_BUTTON_GET_PRIVATE (button);
244     GtkWidget *cell_view = gtk_cell_view_new ();
245
246     /* Store private part */
247     button->priv = priv;
248
249     /* Make sure that the check box is always shown, no matter the value of gtk-button-images */
250     g_signal_connect (cell_view, "notify::visible", G_CALLBACK (gtk_widget_show), NULL);
251
252     /* Create toggle renderer and pack it into the cell view */
253     priv->toggle_renderer = GTK_CELL_RENDERER_TOGGLE (gtk_cell_renderer_toggle_new ());
254     gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cell_view),
255                                 GTK_CELL_RENDERER (priv->toggle_renderer), FALSE);
256
257     /* Add cell view to the image */
258     gtk_button_set_image (GTK_BUTTON (button), cell_view);
259
260     gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
261
262     hildon_check_button_apply_style (GTK_WIDGET (button));
263 }