pcb-rnd knowledge pool
GTK4 rant: CSS and vertical labels
gtk4r_css_vtext by Tibor 'Igor2' Palinkas on 2021-12-23
Tags: insight, gtk4, rant, css, rotation, vertical, text
This rant is part of a series.
CSS label rotation bug
pcb-rnd layer stack is a rather dense packet of information. Since we need to work on small screen, I decided to go for an unusual layout that makes smarter use of screen estate:
- items of a group is printed as a list of text items, one below the other, like in a simple bullet list
- group name is printed on the left side next to the list, as vertical text (label rotated 90 degrees)
The benefit is that the group name does not take up a whole row and does not need to be discriminated from item names using some other method (e.g. bold font).
In gtk2 this was easy to achieve: there is a property of label for rotation, I set it to 90 degrees and almost everything works as expected.
In gtk4 this property get removed, in favor of CSS. CSS is powerful in describing font and text properties, it is easily possible to rotate text by 90 degrees using CSS.
However, there is a huge, conceptual bug in gtk4. Most labels are wide and not very tall: a single line of text, a word or at most a few words. Typically some 15..30 pixels high while hundreds of pixels wide. When rotated by 90 degrees, the sizes swap, the same text suddenly becomes very high and narrow. Unfortunately this is not reflected in widget "allocation" (widget size): gtk still thinks the label is going to be wide and not high. The result is disappointing. Gtk4 allocates a rectangle that is much wider than needed but not high enough, then truncates the text placed in it.
I've asked the developers (who were very helpful), and they said it's "not a bug": CSS is only for the looks and it shouldn't be used to change major properties so the widget sizing code is not prepared for that. I don't agree with that reasoning, but even if I accept it for a moment, then it contradicts with the idea of removing label's rotation property in favor of CSS, because CSS then shouldn't be used to make such drastic change to the layout of the text.
I had another feature that gtk4 was unable to provide: truncated label. Such labels allocate smaller widget that require for displaying the whole text and intentionally truncate text without adding an ellipsis. This is important because the ellipsis hides 1 or 2 letters from the text, and in many practical use cases in pcb-rnd that's like 1/4..1/2 of the whole remaining text. In that situation the ellipsis removes useful information to indicate the obvious, that the text is truncated.
Gtk4 uses Pango for calculating text layout. Pango is a huge spaceship. Unfortunately Pango follows the bondage&discipline design methodology too, so it does not offer a powerful API to let applications build up what they need by combining things from scratch. Instead it offers a turn-key ready solution to text layouts, and in that solution ellipsis is hardwired and can not be turned off.
I figured the easiest way to fix these both is to implement my own custom label widget that simply has a property for 90 degree rotation and another for rendering truncated text without ellipsis. This way I have full control over how the text is laid out and it costs only 165 sloc.