2020-11-02 16:05:57 +00:00
|
|
|
/* Error States
|
2020-09-13 14:37:32 +00:00
|
|
|
*
|
|
|
|
* GtkLabel and GtkEntry can indicate errors if you set the .error
|
|
|
|
* style class on them.
|
|
|
|
*
|
|
|
|
* This examples shows how this can be used in a dialog for input validation.
|
|
|
|
*
|
|
|
|
* It also shows how pass callbacks and objects to GtkBuilder with
|
|
|
|
* GtkBuilderScope and gtk_builder_expose_object().
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <glib/gi18n.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
|
|
|
static void
|
|
|
|
validate_more_details (GtkEntry *entry,
|
|
|
|
GParamSpec *pspec,
|
|
|
|
GtkEntry *details)
|
|
|
|
{
|
|
|
|
if (strlen (gtk_editable_get_text (GTK_EDITABLE (entry))) > 0 &&
|
|
|
|
strlen (gtk_editable_get_text (GTK_EDITABLE (details))) == 0)
|
|
|
|
{
|
|
|
|
gtk_widget_set_tooltip_text (GTK_WIDGET (entry), "Must have details first");
|
|
|
|
gtk_widget_add_css_class (GTK_WIDGET (entry), "error");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gtk_widget_set_tooltip_text (GTK_WIDGET (entry), "");
|
|
|
|
gtk_widget_remove_css_class (GTK_WIDGET (entry), "error");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
mode_switch_state_set (GtkSwitch *sw,
|
|
|
|
gboolean state,
|
|
|
|
GtkWidget *scale)
|
|
|
|
{
|
|
|
|
GtkWidget *label;
|
|
|
|
|
|
|
|
label = GTK_WIDGET (g_object_get_data (G_OBJECT (sw), "error_label"));
|
|
|
|
|
|
|
|
if (!state ||
|
|
|
|
(gtk_range_get_value (GTK_RANGE (scale)) > 50))
|
|
|
|
{
|
|
|
|
gtk_widget_hide (label);
|
|
|
|
gtk_switch_set_state (sw, state);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gtk_widget_show (label);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
level_scale_value_changed (GtkRange *range,
|
|
|
|
GtkWidget *sw)
|
|
|
|
{
|
|
|
|
GtkWidget *label;
|
|
|
|
|
|
|
|
label = GTK_WIDGET (g_object_get_data (G_OBJECT (sw), "error_label"));
|
|
|
|
|
|
|
|
if (gtk_switch_get_active (GTK_SWITCH (sw)) &&
|
|
|
|
!gtk_switch_get_state (GTK_SWITCH (sw)) &&
|
|
|
|
(gtk_range_get_value (range) > 50))
|
|
|
|
{
|
|
|
|
gtk_widget_hide (label);
|
|
|
|
gtk_switch_set_state (GTK_SWITCH (sw), TRUE);
|
|
|
|
}
|
|
|
|
else if (gtk_switch_get_state (GTK_SWITCH (sw)) &&
|
|
|
|
(gtk_range_get_value (range) <= 50))
|
|
|
|
{
|
|
|
|
gtk_switch_set_state (GTK_SWITCH (sw), FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GtkWidget *
|
|
|
|
do_errorstates (GtkWidget *do_widget)
|
|
|
|
{
|
|
|
|
static GtkWidget *window = NULL;
|
|
|
|
|
|
|
|
if (!window)
|
|
|
|
{
|
|
|
|
GtkWidget *toplevel;
|
|
|
|
GtkBuilder *builder;
|
|
|
|
GtkBuilderScope *scope;
|
|
|
|
GtkWidget *sw, *label;
|
|
|
|
|
|
|
|
toplevel = GTK_WIDGET (gtk_widget_get_root (do_widget));
|
|
|
|
|
|
|
|
scope = gtk_builder_cscope_new ();
|
|
|
|
gtk_builder_cscope_add_callback_symbols (GTK_BUILDER_CSCOPE (scope),
|
|
|
|
"validate_more_details", G_CALLBACK (validate_more_details),
|
|
|
|
"mode_switch_state_set", G_CALLBACK (mode_switch_state_set),
|
|
|
|
"level_scale_value_changed", G_CALLBACK (level_scale_value_changed),
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
builder = gtk_builder_new ();
|
|
|
|
gtk_builder_set_scope (builder, scope);
|
|
|
|
gtk_builder_expose_object (builder, "toplevel", G_OBJECT (toplevel));
|
|
|
|
gtk_builder_add_from_resource (builder, "/errorstates/errorstates.ui", NULL);
|
|
|
|
|
|
|
|
window = GTK_WIDGET (gtk_builder_get_object (builder, "dialog"));
|
|
|
|
|
|
|
|
gtk_window_set_display (GTK_WINDOW (window),
|
|
|
|
gtk_widget_get_display (do_widget));
|
|
|
|
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
|
|
|
|
|
|
|
sw = GTK_WIDGET (gtk_builder_get_object (builder, "mode_switch"));
|
|
|
|
label = GTK_WIDGET (gtk_builder_get_object (builder, "error_label"));
|
|
|
|
g_object_set_data (G_OBJECT (sw), "error_label", label);
|
|
|
|
|
|
|
|
g_object_unref (builder);
|
|
|
|
g_object_unref (scope);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!gtk_widget_get_visible (window))
|
|
|
|
gtk_widget_show (window);
|
|
|
|
else
|
|
|
|
gtk_window_destroy (GTK_WINDOW (window));
|
|
|
|
|
|
|
|
return window;
|
|
|
|
}
|