1/* Spin Buttons
2 * #Keywords: GtkEntry
3 *
4 * GtkSpinButton provides convenient ways to input data
5 * that can be seen as a value in a range. The examples
6 * here show that this does not necessarily mean numeric
7 * values, and it can include custom formatting.
8 */
9
10#include <glib/gi18n.h>
11#include <gtk/gtk.h>
12#include <math.h>
13#include <stdlib.h>
14
15G_MODULE_EXPORT int
16spinbutton_hex_spin_input (GtkSpinButton *spin_button,
17 double *new_val)
18{
19 const char *buf;
20 char *err;
21 double res;
22
23 buf = gtk_editable_get_text (GTK_EDITABLE (spin_button));
24 res = strtol (nptr: buf, endptr: &err, base: 16);
25 *new_val = res;
26 if (*err)
27 return GTK_INPUT_ERROR;
28 else
29 return TRUE;
30}
31
32G_MODULE_EXPORT int
33spinbutton_hex_spin_output (GtkSpinButton *spin_button)
34{
35 GtkAdjustment *adjustment;
36 char *buf;
37 double val;
38
39 adjustment = gtk_spin_button_get_adjustment (spin_button);
40 val = gtk_adjustment_get_value (adjustment);
41 if (fabs (x: val) < 1e-5)
42 buf = g_strdup (str: "0x00");
43 else
44 buf = g_strdup_printf (format: "0x%.2X", (int) val);
45 if (strcmp (s1: buf, s2: gtk_editable_get_text (GTK_EDITABLE (spin_button))))
46 gtk_editable_set_text (GTK_EDITABLE (spin_button), text: buf);
47 g_free (mem: buf);
48
49 return TRUE;
50}
51
52G_MODULE_EXPORT int
53spinbutton_time_spin_input (GtkSpinButton *spin_button,
54 double *new_val)
55{
56 const char *text;
57 char **str;
58 gboolean found = FALSE;
59 int hours;
60 int minutes;
61 char *endh;
62 char *endm;
63
64 text = gtk_editable_get_text (GTK_EDITABLE (spin_button));
65 str = g_strsplit (string: text, delimiter: ":", max_tokens: 2);
66
67 if (g_strv_length (str_array: str) == 2)
68 {
69 hours = strtol (nptr: str[0], endptr: &endh, base: 10);
70 minutes = strtol (nptr: str[1], endptr: &endm, base: 10);
71 if (!*endh && !*endm &&
72 0 <= hours && hours < 24 &&
73 0 <= minutes && minutes < 60)
74 {
75 *new_val = hours * 60 + minutes;
76 found = TRUE;
77 }
78 }
79
80 g_strfreev (str_array: str);
81
82 if (!found)
83 {
84 *new_val = 0.0;
85 return GTK_INPUT_ERROR;
86 }
87
88 return TRUE;
89}
90
91G_MODULE_EXPORT int
92spinbutton_time_spin_output (GtkSpinButton *spin_button)
93{
94 GtkAdjustment *adjustment;
95 char *buf;
96 double hours;
97 double minutes;
98
99 adjustment = gtk_spin_button_get_adjustment (spin_button);
100 hours = gtk_adjustment_get_value (adjustment) / 60.0;
101 minutes = (hours - floor (x: hours)) * 60.0;
102 buf = g_strdup_printf (format: "%02.0f:%02.0f", floor (x: hours), floor (x: minutes + 0.5));
103 if (strcmp (s1: buf, s2: gtk_editable_get_text (GTK_EDITABLE (spin_button))))
104 gtk_editable_set_text (GTK_EDITABLE (spin_button), text: buf);
105 g_free (mem: buf);
106
107 return TRUE;
108}
109
110static const char *month[12] = {
111 "January",
112 "February",
113 "March",
114 "April",
115 "May",
116 "June",
117 "July",
118 "August",
119 "September",
120 "October",
121 "November",
122 "December"
123};
124
125G_MODULE_EXPORT int
126spinbutton_month_spin_input (GtkSpinButton *spin_button,
127 double *new_val)
128{
129 int i;
130 char *tmp1, *tmp2;
131 gboolean found = FALSE;
132
133 for (i = 1; i <= 12; i++)
134 {
135 tmp1 = g_ascii_strup (str: month[i - 1], len: -1);
136 tmp2 = g_ascii_strup (str: gtk_editable_get_text (GTK_EDITABLE (spin_button)), len: -1);
137 if (strstr (haystack: tmp1, needle: tmp2) == tmp1)
138 found = TRUE;
139 g_free (mem: tmp1);
140 g_free (mem: tmp2);
141 if (found)
142 break;
143 }
144 if (!found)
145 {
146 *new_val = 0.0;
147 return GTK_INPUT_ERROR;
148 }
149 *new_val = (double) i;
150
151 return TRUE;
152}
153
154G_MODULE_EXPORT int
155spinbutton_month_spin_output (GtkSpinButton *spin_button)
156{
157 GtkAdjustment *adjustment;
158 double value;
159 int i;
160
161 adjustment = gtk_spin_button_get_adjustment (spin_button);
162 value = gtk_adjustment_get_value (adjustment);
163 for (i = 1; i <= 12; i++)
164 if (fabs (x: value - (double)i) < 1e-5)
165 {
166 if (strcmp (s1: month[i-1], s2: gtk_editable_get_text (GTK_EDITABLE (spin_button))))
167 gtk_editable_set_text (GTK_EDITABLE (spin_button), text: month[i-1]);
168 }
169
170 return TRUE;
171}
172
173static gboolean
174value_to_label (GBinding *binding,
175 const GValue *from,
176 GValue *to,
177 gpointer user_data)
178{
179 g_value_take_string (value: to, v_string: g_strdup_printf (format: "%g", g_value_get_double (value: from)));
180 return TRUE;
181}
182
183GtkWidget *
184do_spinbutton (GtkWidget *do_widget)
185{
186 static GtkWidget *window;
187
188 if (!window)
189 {
190 GtkBuilder *builder;
191 GtkAdjustment *adj;
192 GtkWidget *label;
193
194 builder = gtk_builder_new_from_resource (resource_path: "/spinbutton/spinbutton.ui");
195 window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
196 gtk_window_set_display (GTK_WINDOW (window),
197 display: gtk_widget_get_display (widget: do_widget));
198 gtk_window_set_title (GTK_WINDOW (window), title: "Spin Buttons");
199 gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
200 g_object_add_weak_pointer (G_OBJECT (window), weak_pointer_location: (gpointer *)&window);
201
202 adj = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "basic_adjustment"));
203 label = GTK_WIDGET (gtk_builder_get_object (builder, "basic_label"));
204 g_object_bind_property_full (source: adj, source_property: "value",
205 target: label, target_property: "label",
206 flags: G_BINDING_SYNC_CREATE,
207 transform_to: value_to_label,
208 NULL,
209 NULL, NULL);
210 adj = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "hex_adjustment"));
211 label = GTK_WIDGET (gtk_builder_get_object (builder, "hex_label"));
212 g_object_bind_property_full (source: adj, source_property: "value",
213 target: label, target_property: "label",
214 flags: G_BINDING_SYNC_CREATE,
215 transform_to: value_to_label,
216 NULL,
217 NULL, NULL);
218 adj = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "time_adjustment"));
219 label = GTK_WIDGET (gtk_builder_get_object (builder, "time_label"));
220 g_object_bind_property_full (source: adj, source_property: "value",
221 target: label, target_property: "label",
222 flags: G_BINDING_SYNC_CREATE,
223 transform_to: value_to_label,
224 NULL,
225 NULL, NULL);
226 adj = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "month_adjustment"));
227 label = GTK_WIDGET (gtk_builder_get_object (builder, "month_label"));
228 g_object_bind_property_full (source: adj, source_property: "value",
229 target: label, target_property: "label",
230 flags: G_BINDING_SYNC_CREATE,
231 transform_to: value_to_label,
232 NULL,
233 NULL, NULL);
234
235 g_object_unref (object: builder);
236 }
237
238 if (!gtk_widget_get_visible (widget: window))
239 gtk_widget_show (widget: window);
240 else
241 gtk_window_destroy (GTK_WINDOW (window));
242
243 return window;
244}
245

source code of gtk/demos/gtk-demo/spinbutton.c