How to set font size for a TextView at runtime?

[i’m not using gtksourceview but i tagged it because sourceview also does stuff with textview styling]

i’m looking for the equivalant of this dom code:

const view = document.createElement("textarea");
view.style.fontSize = some_value;

the docs Gtk – 4.0: Text Widget Overview have two examples of setting style for a textview:

1:

/* Change default font and color throughout the widget */
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (provider,
                                 "textview {"
                                 " font: 15px serif;"
                                 "  color: green;"
                                 "}",
                                 -1);
context = gtk_widget_get_style_context (view);
gtk_style_context_add_provider (context,
                                GTK_STYLE_PROVIDER (provider),
                                GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);

here, it accepts a full css string, and there doesn’t seem to be a way to change it dynamically. in theeory, one could template the string at runtime, but that would be ew, just disgusting to do

also this api is deprecated, the docs say “The relevant API has been moved to GtkWidget where applicable”, but this is just a link to the Widget class, not any style method

2:

/* Change left margin throughout the widget */
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 30);

/* Use a tag to change the color for just one part of the widget */
tag = gtk_text_buffer_create_tag (buffer, "blue_foreground",
                                  "foreground", "blue",
                                  NULL);
gtk_text_buffer_get_iter_at_offset (buffer, &start, 7);
gtk_text_buffer_get_iter_at_offset (buffer, &end, 12);
gtk_text_buffer_apply_tag (buffer, tag, &start, &end);

this one looks good: TextTag has a :scale property, which is what i need.

i tried it, and it seems to work at first, but if i type something at the end or beginning of the text, it types outside of the tag, and so the new text is not scaled correctly

i could remove and reapply the tag on the whole view on each change, but that would probably mess with asian input methods, screen keyboards, screen readers, etc

so… this looks like a basic thing, but i’ve spent an hour failing, what am i missing here?

If it can help, for GTK 3 there is TeplPango: libgedit-tepl 6 Reference Manual

You can also look at the gedit Text Size plugin: plugins/textsize · master · World / gedit / gedit · GitLab (especially gedit-text-size-view-activatable.c).

Yes, it’s a lot of code, GTK 3 deprecated some convenient functions for doing that. Is it a good thing or not, I don’t know.

Look at Gtk.TextTag:font or font-desc

1 Like

yes tags works but

    Gtk.TextIter start0;
    buffer.get_start_iter (out start0);
    var tag = buffer.create_tag ("");
    tag.scale = 2;
    buffer.insert_with_tags (ref start0, "some initial text", -1, tag);

GtkTextTags don’t have a gravity configuration.

If this were done with GtkTextMarks, the start mark would have a left gravity, and the end mark would have right gravity.

A utility could be written to have that behavior for a GtkTextTag. By listening to the GtkTextBuffer::insert-text signal and applying the tag to new regions of text. A bit ugly but it’s doable.

Or is there a better alternative? For example in GTK 4 there is also the GtkTextTag:insert-hyphens property that ought to be configured for the whole buffer in certain apps.

For keeping a tag applied to a whole buffer, I personally do something like this (python):

tag = buffer.create_tag('default-style', show_spaces='ignorables', insert_hyphens=False)
tag.set_priority(0)   # lowest
buffer.connect('changed', lambda _buf: _buf.apply_tag_by_name('default-style', *_buf.get_bounds()))

(yes, it’s ugly, but it works fine).

Internally, Gtk uses a default text attributes, but sadly users don’t have access to it…

1 Like

What is deprecated is to apply a style to a widget’s style context. You can apply the CSS to the GdkDisplay instead.

Edit: for info, I’m using a runtime-generated style like textview {font-size: 150%;} for zooming the text in one of my apps.

At run-time, you can add a style provider with gtk_style_context_add_provider_for_display, then remove it with gtk_style_context_remove_provider_for_display, and create and add a new provider with a different style.

Sometimes it seems to be necessary to use the subnode as selector: “textview text {color:red;}”. In newer GTK versions, it also is better to use a different font description method, not simply “font”, but font-family, font-size, font-weight, etc.

That’s not even required: just use the same CssProvider, and call load_from_data() again, it will replace the old content with the new provided one :slight_smile:

1 Like

yes, the problem is this, i can’t set it per view, only for all views at once. i could add a class, but still, if you open another file in a second tab or window, it would also affect its textview too because it’s made from the same template and has the same class.

Can you set the name to a particular view instance with gtk_widget_set_name?

Then you can use this name as selector. The style is global, but only widget(s) with the given name will match.

so something like?

    var name = "_%p".printf (textview);
    textview.set_name (name);
    var css = @"#$(name) {font-size: $(pt)pt;}";
1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.