1#include <stdlib.h>
2#include <gtk/gtk.h>
3
4static gboolean
5boolean_to_text (GBinding *binding,
6 const GValue *source,
7 GValue *target,
8 gpointer dummy G_GNUC_UNUSED)
9{
10 if (g_value_get_boolean (value: source))
11 g_value_set_string (value: target, v_string: "Enabled");
12 else
13 g_value_set_string (value: target, v_string: "Disabled");
14
15 return TRUE;
16}
17
18static GtkWidget *
19make_switch (gboolean is_on,
20 gboolean is_sensitive)
21{
22 GtkWidget *hbox;
23 GtkWidget *sw, *label;
24
25 hbox = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 6);
26
27 sw = gtk_switch_new ();
28 gtk_switch_set_active (GTK_SWITCH (sw), is_active: is_on);
29 gtk_box_append (GTK_BOX (hbox), child: sw);
30 gtk_widget_set_sensitive (widget: sw, sensitive: is_sensitive);
31
32 label = gtk_label_new (str: is_on ? "Enabled" : "Disabled");
33 gtk_widget_set_hexpand (widget: label, TRUE);
34 gtk_box_append (GTK_BOX (hbox), child: label);
35
36 g_object_bind_property_full (source: sw, source_property: "active",
37 target: label, target_property: "label",
38 flags: G_BINDING_DEFAULT,
39 transform_to: boolean_to_text,
40 NULL,
41 NULL, NULL);
42
43 return hbox;
44}
45
46typedef struct {
47 GtkSwitch *sw;
48 gboolean state;
49} SetStateData;
50
51static gboolean
52set_state_delayed (gpointer data)
53{
54 SetStateData *d = data;
55
56 gtk_switch_set_state (self: d->sw, state: d->state);
57
58 g_object_set_data (G_OBJECT (d->sw), key: "timeout", NULL);
59
60 return G_SOURCE_REMOVE;
61}
62
63static gboolean
64set_state (GtkSwitch *sw, gboolean state, gpointer data)
65{
66 SetStateData *d;
67 guint id;
68
69 id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (sw), "timeout"));
70
71 if (id != 0)
72 g_source_remove (tag: id);
73
74 d = g_new (SetStateData, 1);
75 d->sw = sw;
76 d->state = state;
77
78 id = g_timeout_add_full (G_PRIORITY_DEFAULT, interval: 2000, function: set_state_delayed, data: d, notify: g_free);
79 g_object_set_data (G_OBJECT (sw), key: "timeout", GUINT_TO_POINTER (id));
80
81 return TRUE;
82}
83
84static void
85sw_delay_notify (GObject *obj, GParamSpec *pspec, gpointer data)
86{
87 GtkWidget *spinner = data;
88 gboolean active;
89 gboolean state;
90
91 g_object_get (object: obj,
92 first_property_name: "active", &active,
93 "state", &state,
94 NULL);
95
96 if (active != state)
97 {
98 gtk_spinner_start (GTK_SPINNER (spinner));
99 gtk_widget_set_opacity (widget: spinner, opacity: 1.0);
100 }
101 else
102 {
103 gtk_widget_set_opacity (widget: spinner, opacity: 0.0);
104 gtk_spinner_stop (GTK_SPINNER (spinner));
105 }
106}
107
108static GtkWidget *
109make_delayed_switch (gboolean is_on,
110 gboolean is_sensitive)
111{
112 GtkWidget *hbox;
113 GtkWidget *sw, *label, *spinner, *check;
114
115 hbox = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 6);
116
117 sw = gtk_switch_new ();
118 gtk_switch_set_active (GTK_SWITCH (sw), is_active: is_on);
119 gtk_box_append (GTK_BOX (hbox), child: sw);
120 gtk_widget_set_sensitive (widget: sw, sensitive: is_sensitive);
121
122 g_signal_connect (sw, "state-set", G_CALLBACK (set_state), NULL);
123
124 spinner = gtk_spinner_new ();
125 gtk_box_append (GTK_BOX (hbox), child: spinner);
126 gtk_widget_set_opacity (widget: spinner, opacity: 0.0);
127
128 label = gtk_label_new (str: is_on ? "Enabled" : "Disabled");
129 gtk_widget_set_hexpand (widget: label, TRUE);
130 gtk_box_append (GTK_BOX (hbox), child: label);
131
132 g_object_bind_property_full (source: sw, source_property: "active",
133 target: label, target_property: "label",
134 flags: G_BINDING_DEFAULT,
135 transform_to: boolean_to_text,
136 NULL,
137 NULL, NULL);
138
139 check = gtk_check_button_new ();
140 gtk_box_append (GTK_BOX (hbox), child: check);
141 g_object_bind_property (source: sw, source_property: "state",
142 target: check, target_property: "active",
143 flags: G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
144
145 g_signal_connect (sw, "notify", G_CALLBACK (sw_delay_notify), spinner);
146
147 return hbox;
148}
149
150static void
151quit_cb (GtkWidget *widget,
152 gpointer data)
153{
154 gboolean *done = data;
155
156 *done = TRUE;
157
158 g_main_context_wakeup (NULL);
159}
160
161int main (int argc, char *argv[])
162{
163 GtkWidget *window;
164 GtkWidget *vbox, *hbox;
165 gboolean done = FALSE;
166
167 gtk_init ();
168
169 window = gtk_window_new ();
170 gtk_window_set_title (GTK_WINDOW (window), title: "GtkSwitch");
171 gtk_window_set_default_size (GTK_WINDOW (window), width: 400, height: -1);
172 g_signal_connect (window, "destroy", G_CALLBACK (quit_cb), &done);
173 gtk_widget_show (widget: window);
174
175 vbox = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 12);
176 gtk_window_set_child (GTK_WINDOW (window), child: vbox);
177
178 hbox = make_switch (FALSE, TRUE);
179 gtk_box_append (GTK_BOX (vbox), child: hbox);
180
181 hbox = make_switch (TRUE, TRUE);
182 gtk_box_append (GTK_BOX (vbox), child: hbox);
183
184 hbox = make_switch (FALSE, FALSE);
185 gtk_box_append (GTK_BOX (vbox), child: hbox);
186
187 hbox = make_switch (TRUE, FALSE);
188 gtk_box_append (GTK_BOX (vbox), child: hbox);
189
190 hbox = make_delayed_switch (FALSE, TRUE);
191 gtk_box_append (GTK_BOX (vbox), child: hbox);
192
193 while (!done)
194 g_main_context_iteration (NULL, TRUE);
195
196 return EXIT_SUCCESS;
197}
198

source code of gtk/tests/testswitch.c