/* Spin Button * * GtkSpinButton provides convenient ways to input data * that can be seen as a value in a range. The examples * here show that this does not necessarily mean numeric * values, and it can include custom formatting. */ #include #include #include #include static gint hex_spin_input (GtkSpinButton *spin_button, gdouble *new_val) { const gchar *buf; gchar *err; gdouble res; buf = gtk_editable_get_text (GTK_EDITABLE (spin_button)); res = strtol (buf, &err, 16); *new_val = res; if (*err) return GTK_INPUT_ERROR; else return TRUE; } static gint hex_spin_output (GtkSpinButton *spin_button) { GtkAdjustment *adjustment; gchar *buf; gdouble val; adjustment = gtk_spin_button_get_adjustment (spin_button); val = gtk_adjustment_get_value (adjustment); if (fabs (val) < 1e-5) buf = g_strdup ("0x00"); else buf = g_strdup_printf ("0x%.2X", (gint) val); if (strcmp (buf, gtk_editable_get_text (GTK_EDITABLE (spin_button)))) gtk_editable_set_text (GTK_EDITABLE (spin_button), buf); g_free (buf); return TRUE; } static gint time_spin_input (GtkSpinButton *spin_button, gdouble *new_val) { const gchar *text; gchar **str; gboolean found = FALSE; gint hours; gint minutes; gchar *endh; gchar *endm; text = gtk_editable_get_text (GTK_EDITABLE (spin_button)); str = g_strsplit (text, ":", 2); if (g_strv_length (str) == 2) { hours = strtol (str[0], &endh, 10); minutes = strtol (str[1], &endm, 10); if (!*endh && !*endm && 0 <= hours && hours < 24 && 0 <= minutes && minutes < 60) { *new_val = hours * 60 + minutes; found = TRUE; } } g_strfreev (str); if (!found) { *new_val = 0.0; return GTK_INPUT_ERROR; } return TRUE; } static gint time_spin_output (GtkSpinButton *spin_button) { GtkAdjustment *adjustment; gchar *buf; gdouble hours; gdouble minutes; adjustment = gtk_spin_button_get_adjustment (spin_button); hours = gtk_adjustment_get_value (adjustment) / 60.0; minutes = (hours - floor (hours)) * 60.0; buf = g_strdup_printf ("%02.0f:%02.0f", floor (hours), floor (minutes + 0.5)); if (strcmp (buf, gtk_editable_get_text (GTK_EDITABLE (spin_button)))) gtk_editable_set_text (GTK_EDITABLE (spin_button), buf); g_free (buf); return TRUE; } static gchar *month[12] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; static gint month_spin_input (GtkSpinButton *spin_button, gdouble *new_val) { gint i; gchar *tmp1, *tmp2; gboolean found = FALSE; for (i = 1; i <= 12; i++) { tmp1 = g_ascii_strup (month[i - 1], -1); tmp2 = g_ascii_strup (gtk_editable_get_text (GTK_EDITABLE (spin_button)), -1); if (strstr (tmp1, tmp2) == tmp1) found = TRUE; g_free (tmp1); g_free (tmp2); if (found) break; } if (!found) { *new_val = 0.0; return GTK_INPUT_ERROR; } *new_val = (gdouble) i; return TRUE; } static gint month_spin_output (GtkSpinButton *spin_button) { GtkAdjustment *adjustment; gdouble value; gint i; adjustment = gtk_spin_button_get_adjustment (spin_button); value = gtk_adjustment_get_value (adjustment); for (i = 1; i <= 12; i++) if (fabs (value - (double)i) < 1e-5) { if (strcmp (month[i-1], gtk_editable_get_text (GTK_EDITABLE (spin_button)))) gtk_editable_set_text (GTK_EDITABLE (spin_button), month[i-1]); } return TRUE; } static gboolean value_to_label (GBinding *binding, const GValue *from, GValue *to, gpointer user_data) { g_value_take_string (to, g_strdup_printf ("%g", g_value_get_double (from))); return TRUE; } GtkWidget * do_spinbutton (GtkWidget *do_widget) { static GtkWidget *window; if (!window) { GtkBuilder *builder; GtkAdjustment *adj; GtkWidget *label; builder = gtk_builder_new_from_resource ("/spinbutton/spinbutton.ui"); gtk_builder_add_callback_symbols (builder, "hex_spin_input", G_CALLBACK (hex_spin_input), "hex_spin_output", G_CALLBACK (hex_spin_output), "time_spin_input", G_CALLBACK (time_spin_input), "time_spin_output", G_CALLBACK (time_spin_output), "month_spin_input", G_CALLBACK (month_spin_input), "month_spin_output", G_CALLBACK (month_spin_output), NULL); gtk_builder_connect_signals (builder, NULL); window = GTK_WIDGET (gtk_builder_get_object (builder, "window")); gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget)); gtk_window_set_title (GTK_WINDOW (window), "Spin Buttons"); gtk_window_set_resizable (GTK_WINDOW (window), FALSE); g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window); adj = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "basic_adjustment")); label = GTK_WIDGET (gtk_builder_get_object (builder, "basic_label")); g_object_bind_property_full (adj, "value", label, "label", G_BINDING_SYNC_CREATE, value_to_label, NULL, NULL, NULL); adj = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "hex_adjustment")); label = GTK_WIDGET (gtk_builder_get_object (builder, "hex_label")); g_object_bind_property_full (adj, "value", label, "label", G_BINDING_SYNC_CREATE, value_to_label, NULL, NULL, NULL); adj = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "time_adjustment")); label = GTK_WIDGET (gtk_builder_get_object (builder, "time_label")); g_object_bind_property_full (adj, "value", label, "label", G_BINDING_SYNC_CREATE, value_to_label, NULL, NULL, NULL); adj = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "month_adjustment")); label = GTK_WIDGET (gtk_builder_get_object (builder, "month_label")); g_object_bind_property_full (adj, "value", label, "label", G_BINDING_SYNC_CREATE, value_to_label, NULL, NULL, NULL); g_object_unref (builder); } if (!gtk_widget_get_visible (window)) gtk_widget_show (window); else gtk_widget_destroy (window); return window; }