Vala - How to set color of Gtk4.Label programatically?

Viewed 79

I have a Gtk4 Gtk.Label.

I want to change it's color & size attribute programatically.

The markup way <span foreground='red' size='large'> is easy to use.

But after some time, I want to remove these styles and make label colorless again.

I used my_lbl.label = my_lbl.get_text(); to unstylize it.


What is the PangoAttribute way to stylize a label?

How can I do this without markup labels?

Thanks!

2 Answers

Like NoDakker already replied, GTK re-uses CSS as a styling language instead of inventing its own.

What applications in your situation usually do is the following: they create a CSS file, e.g. "myapp.css", and load it using GtkCssProvider's API, like gtk_css_provider_load_from_resource(). Then they add it for the whole application

GdkDisplay *display = gdk_display_get_default ();
GtkCssProvider *provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/org/myapp/my-app.css");
gtk_style_context_add_provider_for_display (display,
                                            GTK_STYLE_PROVIDER (provider),
                                            GTK_STYLE_PROVIDER_PRIORITY_FALLBACK);
g_object_unref (provider);

or in Vala

var provider = new Gtk.CssProvider ();
provider.load_from_resource ("/org/myapp/my-app.css");
Gtk.StyleContext.add_provider_for_display (Gdk.Display.get_default (),
                                           provider,
                                           Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);

Next, in the CSS file, they usually create CSS classes. For example, a common use case similar to yours is to mark something as "bad" or "error", so you would get something like

.error {
    color: red;
}

Finally, in your code, you can then easily add or remove the class from a widget when needed, with gtk_widget_add_css_class

static void
validate_input (GtkWidget *input)
{
    if (input_is_valid (input))
        gtk_widget_remove_css_class (input, "error");
    else
        gtk_widget_add_css_class (input, "error");
}

or in Vala

private void validate_input (Gtk.Widget input) {
    if (input_is_valid (input))
        input.remove_css_class ("error");
    else
        input.add_css_class ("error");
}

Basically, the direction the GTK4 folks want coders to go regarding attribute modification is through the use of cascading style sheet (CSS) directives using CSS provider objects.

In an example program, I utilized a CSS provider to change color of a label based upon the state of a switch widget. The program is a bit large so I only am including snippets pertaining to the label color change.

First off, a CSS provider object was defined.

    GtkCssProvider  *provider;

Then the provider was initialized with a data string to indicate any object with a class name of "green" would have a green background and any object with a class name of "red" would have a red background. The provider is then assigned to the label widget ("indicator").

gtk_css_provider_load_from_data(provider, "#green { background-image: none; background-color: #00aa00; color: white; font-weight: bold; border-radius: 6px; margin-left: 4px; } \
 #red {background-image: none; background-color: #cc0000; color: white; font-weight: bold; border-radius: 6px; margin-left: 4px;}", -1);
gtk_style_context_add_provider(gtk_widget_get_style_context(indicator), GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
gtk_widget_set_name(indicator, "red"); /* "indicator is the name of the label widget */

Then, I set up a callback function attached to a switch widget that would check the current name property of the widget and toggle the widget class name (either from "green" to "red" or "red" to "green"). One could connect to a check button signal or other widget signal.

static void toggle_indicator(GtkWidget *widget)
{
    if((strcmp(gtk_widget_get_name(widget), "green"))== 0)
    {
        gtk_widget_set_name(widget, "red");
        gtk_label_set_text(GTK_LABEL(widget), "Off");
    }
    else
    {
        gtk_widget_set_name(widget, "green");
        gtk_label_set_text(GTK_LABEL(widget), "On");
    }
}

Running the program results in the label color change.

Sample of label color change

I'm not sure if this addresses the issue in a manner that is acceptable to you, but as I noted, the statement of direction for setting attributes such as colors in GTK4 is to utilize CSS.

Hope this helps.

Regards.

Related