1 | #include <stdlib.h> |
2 | #include <gtk/gtk.h> |
3 | |
4 | static gboolean |
5 | boolean_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 | |
18 | static GtkWidget * |
19 | make_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 | |
46 | typedef struct { |
47 | GtkSwitch *sw; |
48 | gboolean state; |
49 | } SetStateData; |
50 | |
51 | static gboolean |
52 | set_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 | |
63 | static gboolean |
64 | set_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 | |
84 | static void |
85 | sw_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 | |
108 | static GtkWidget * |
109 | make_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 | |
150 | static void |
151 | quit_cb (GtkWidget *widget, |
152 | gpointer data) |
153 | { |
154 | gboolean *done = data; |
155 | |
156 | *done = TRUE; |
157 | |
158 | g_main_context_wakeup (NULL); |
159 | } |
160 | |
161 | int 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 | |