1/* Error States
2 *
3 * GtkLabel and GtkEntry can indicate errors if you set the .error
4 * style class on them.
5 *
6 * This examples shows how this can be used in a dialog for input validation.
7 *
8 * It also shows how pass callbacks and objects to GtkBuilder with
9 * GtkBuilderScope and gtk_builder_expose_object().
10 */
11
12#include <glib/gi18n.h>
13#include <gtk/gtk.h>
14
15static void
16validate_more_details (GtkEntry *entry,
17 GParamSpec *pspec,
18 GtkEntry *details)
19{
20 if (strlen (s: gtk_editable_get_text (GTK_EDITABLE (entry))) > 0 &&
21 strlen (s: gtk_editable_get_text (GTK_EDITABLE (details))) == 0)
22 {
23 gtk_widget_set_tooltip_text (GTK_WIDGET (entry), text: "Must have details first");
24 gtk_widget_add_css_class (GTK_WIDGET (entry), css_class: "error");
25 }
26 else
27 {
28 gtk_widget_set_tooltip_text (GTK_WIDGET (entry), text: "");
29 gtk_widget_remove_css_class (GTK_WIDGET (entry), css_class: "error");
30 }
31}
32
33static gboolean
34mode_switch_state_set (GtkSwitch *sw,
35 gboolean state,
36 GtkWidget *scale)
37{
38 GtkWidget *label;
39
40 label = GTK_WIDGET (g_object_get_data (G_OBJECT (sw), "error_label"));
41
42 if (!state ||
43 (gtk_range_get_value (GTK_RANGE (scale)) > 50))
44 {
45 gtk_widget_hide (widget: label);
46 gtk_switch_set_state (self: sw, state);
47 }
48 else
49 {
50 gtk_widget_show (widget: label);
51 }
52
53 return TRUE;
54}
55
56static void
57level_scale_value_changed (GtkRange *range,
58 GtkWidget *sw)
59{
60 GtkWidget *label;
61
62 label = GTK_WIDGET (g_object_get_data (G_OBJECT (sw), "error_label"));
63
64 if (gtk_switch_get_active (GTK_SWITCH (sw)) &&
65 !gtk_switch_get_state (GTK_SWITCH (sw)) &&
66 (gtk_range_get_value (range) > 50))
67 {
68 gtk_widget_hide (widget: label);
69 gtk_switch_set_state (GTK_SWITCH (sw), TRUE);
70 }
71 else if (gtk_switch_get_state (GTK_SWITCH (sw)) &&
72 (gtk_range_get_value (range) <= 50))
73 {
74 gtk_switch_set_state (GTK_SWITCH (sw), FALSE);
75 }
76}
77
78GtkWidget *
79do_errorstates (GtkWidget *do_widget)
80{
81 static GtkWidget *window = NULL;
82
83 if (!window)
84 {
85 GtkWidget *toplevel;
86 GtkBuilder *builder;
87 GtkBuilderScope *scope;
88 GtkWidget *sw, *label;
89
90 toplevel = GTK_WIDGET (gtk_widget_get_root (do_widget));
91
92 scope = gtk_builder_cscope_new ();
93 gtk_builder_cscope_add_callback_symbols (self: GTK_BUILDER_CSCOPE (ptr: scope),
94 first_callback_name: "validate_more_details", G_CALLBACK (validate_more_details),
95 "mode_switch_state_set", G_CALLBACK (mode_switch_state_set),
96 "level_scale_value_changed", G_CALLBACK (level_scale_value_changed),
97 NULL);
98
99 builder = gtk_builder_new ();
100 gtk_builder_set_scope (builder, scope);
101 gtk_builder_expose_object (builder, name: "toplevel", G_OBJECT (toplevel));
102 gtk_builder_add_from_resource (builder, resource_path: "/errorstates/errorstates.ui", NULL);
103
104 window = GTK_WIDGET (gtk_builder_get_object (builder, "dialog"));
105
106 gtk_window_set_display (GTK_WINDOW (window),
107 display: gtk_widget_get_display (widget: do_widget));
108 g_object_add_weak_pointer (G_OBJECT (window), weak_pointer_location: (gpointer *)&window);
109
110 sw = GTK_WIDGET (gtk_builder_get_object (builder, "mode_switch"));
111 label = GTK_WIDGET (gtk_builder_get_object (builder, "error_label"));
112 g_object_set_data (G_OBJECT (sw), key: "error_label", data: label);
113
114 g_object_unref (object: builder);
115 g_object_unref (object: scope);
116 }
117
118 if (!gtk_widget_get_visible (widget: window))
119 gtk_widget_show (widget: window);
120 else
121 gtk_window_destroy (GTK_WINDOW (window));
122
123 return window;
124}
125

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