| #include <stdlib.h> |
| #include <gtk/gtk.h> |
| |
| static gboolean |
| boolean_to_text (GBinding *binding, |
| const GValue *source, |
| GValue *target, |
| gpointer dummy G_GNUC_UNUSED) |
| { |
| if (g_value_get_boolean (source)) |
| g_value_set_string (target, "Enabled"); |
| else |
| g_value_set_string (target, "Disabled"); |
| |
| return TRUE; |
| } |
| |
| static GtkWidget * |
| make_switch (gboolean is_on, |
| gboolean is_sensitive) |
| { |
| GtkWidget *hbox; |
| GtkWidget *sw, *label; |
| |
| hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); |
| |
| sw = gtk_switch_new (); |
| gtk_switch_set_active (GTK_SWITCH (sw), is_on); |
| gtk_box_append (GTK_BOX (hbox), sw); |
| gtk_widget_set_sensitive (sw, is_sensitive); |
| |
| label = gtk_label_new (is_on ? "Enabled" : "Disabled"); |
| gtk_widget_set_hexpand (label, TRUE); |
| gtk_box_append (GTK_BOX (hbox), label); |
| |
| g_object_bind_property_full (sw, "active", |
| label, "label", |
| G_BINDING_DEFAULT, |
| boolean_to_text, |
| NULL, |
| NULL, NULL); |
| |
| return hbox; |
| } |
| |
| typedef struct { |
| GtkSwitch *sw; |
| gboolean state; |
| } SetStateData; |
| |
| static gboolean |
| set_state_delayed (gpointer data) |
| { |
| SetStateData *d = data; |
| |
| gtk_switch_set_state (d->sw, d->state); |
| |
| g_object_set_data (G_OBJECT (d->sw), "timeout", NULL); |
| |
| return G_SOURCE_REMOVE; |
| } |
| |
| static gboolean |
| set_state (GtkSwitch *sw, gboolean state, gpointer data) |
| { |
| SetStateData *d; |
| guint id; |
| |
| id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (sw), "timeout")); |
| |
| if (id != 0) |
| g_source_remove (id); |
| |
| d = g_new (SetStateData, 1); |
| d->sw = sw; |
| d->state = state; |
| |
| id = g_timeout_add_full (G_PRIORITY_DEFAULT, 2000, set_state_delayed, d, g_free); |
| g_object_set_data (G_OBJECT (sw), "timeout", GUINT_TO_POINTER (id)); |
| |
| return TRUE; |
| } |
| |
| static void |
| sw_delay_notify (GObject *obj, GParamSpec *pspec, gpointer data) |
| { |
| GtkWidget *spinner = data; |
| gboolean active; |
| gboolean state; |
| |
| g_object_get (obj, |
| "active", &active, |
| "state", &state, |
| NULL); |
| |
| if (active != state) |
| { |
| gtk_spinner_start (GTK_SPINNER (spinner)); |
| gtk_widget_set_opacity (spinner, 1.0); |
| } |
| else |
| { |
| gtk_widget_set_opacity (spinner, 0.0); |
| gtk_spinner_stop (GTK_SPINNER (spinner)); |
| } |
| } |
| |
| static GtkWidget * |
| make_delayed_switch (gboolean is_on, |
| gboolean is_sensitive) |
| { |
| GtkWidget *hbox; |
| GtkWidget *sw, *label, *spinner, *check; |
| |
| hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); |
| |
| sw = gtk_switch_new (); |
| gtk_switch_set_active (GTK_SWITCH (sw), is_on); |
| gtk_box_append (GTK_BOX (hbox), sw); |
| gtk_widget_set_sensitive (sw, is_sensitive); |
| |
| g_signal_connect (sw, "state-set", G_CALLBACK (set_state), NULL); |
| |
| spinner = gtk_spinner_new (); |
| gtk_box_append (GTK_BOX (hbox), spinner); |
| gtk_widget_set_opacity (spinner, 0.0); |
| |
| label = gtk_label_new (is_on ? "Enabled" : "Disabled"); |
| gtk_widget_set_hexpand (label, TRUE); |
| gtk_box_append (GTK_BOX (hbox), label); |
| |
| g_object_bind_property_full (sw, "active", |
| label, "label", |
| G_BINDING_DEFAULT, |
| boolean_to_text, |
| NULL, |
| NULL, NULL); |
| |
| check = gtk_check_button_new (); |
| gtk_box_append (GTK_BOX (hbox), check); |
| g_object_bind_property (sw, "state", |
| check, "active", |
| G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); |
| |
| g_signal_connect (sw, "notify", G_CALLBACK (sw_delay_notify), spinner); |
| |
| return hbox; |
| } |
| |
| static void |
| quit_cb (GtkWidget *widget, |
| gpointer data) |
| { |
| gboolean *done = data; |
| |
| *done = TRUE; |
| |
| g_main_context_wakeup (NULL); |
| } |
| |
| int main (int argc, char *argv[]) |
| { |
| GtkWidget *window; |
| GtkWidget *vbox, *hbox; |
| gboolean done = FALSE; |
| |
| gtk_init (); |
| |
| window = gtk_window_new (); |
| gtk_window_set_title (GTK_WINDOW (window), "GtkSwitch"); |
| gtk_window_set_default_size (GTK_WINDOW (window), 400, -1); |
| g_signal_connect (window, "destroy", G_CALLBACK (quit_cb), &done); |
| gtk_window_present (GTK_WINDOW (window)); |
| |
| vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); |
| gtk_window_set_child (GTK_WINDOW (window), vbox); |
| |
| hbox = make_switch (FALSE, TRUE); |
| gtk_box_append (GTK_BOX (vbox), hbox); |
| |
| hbox = make_switch (TRUE, TRUE); |
| gtk_box_append (GTK_BOX (vbox), hbox); |
| |
| hbox = make_switch (FALSE, FALSE); |
| gtk_box_append (GTK_BOX (vbox), hbox); |
| |
| hbox = make_switch (TRUE, FALSE); |
| gtk_box_append (GTK_BOX (vbox), hbox); |
| |
| hbox = make_delayed_switch (FALSE, TRUE); |
| gtk_box_append (GTK_BOX (vbox), hbox); |
| |
| while (!done) |
| g_main_context_iteration (NULL, TRUE); |
| |
| return EXIT_SUCCESS; |
| } |