Getting control over GtkLabel width

I’m having trouble controlling the width of GtkLabel in my app. Here’s the context:

  • There’s a window showing icons in a grid, each one having an associated label.
  • The layout looks fine in English, but in many translations the labels are too long, making the layout too sparse.
  • Up till now I’ve truncated/ellipsized long labels at 15 characters. That works, but users whose language is not English don’t like it much!
  • So my next thought is: insist on the label-width limit but get long labels to wrap onto a second line if necessary. (The labels include spaces so word-wrapping should work.)

The thing is that I can’t get the wrapping to work as intended. I’m trying two APIs for the widget that includes the labels: GtkGrid and (yes, I know it’s deprecated) GtkTable. In each case there’s a problem.

  • With GtkGrid, the labels end up wider than the specified maximum number of characters (15).
  • With GtkTable, some of the labels end up wrapped onto 3 lines, even though they would fit on 2 lines given the 15-character width limit.

Here are links to a minimal example C file and screenshot:
c-file
screenshot

Does the problem occur with only ASCII character labels too, or only with your foreign language unicode strings that are contained in your provided example code? It is for GTK4 I assume? With GTK4 I had a wrapping issue myself, an example was working with GTK 3.97 but for 4.0 text was not wrapped. I have not yet further investigated that issue (GTK4 for Graphical User Interfaces).

According to the reference manual:

For wrapping labels, width-chars is used as the minimum width, if specified, and max-width-chars is used as the natural width. Even if max-width-chars specified, wrapping labels will be rewrapped to use all of the available width.

So where the label wraps depends on the allocated space width.

OK, I see that working now, if I resize the window holding the labels. But It’s tricky to ensure it will look good by specifying a default window size, since the actual result will depend on the user’s choice of font size.

I presume that “characters” in GTK always means UTF-8 characters, so I don’t think plain ASCII versus accented characters should make a difference in this context.

What is good in this context is quite subjective and at high bikeshedding risk. I would personally get rid of any width-chars and max-width-chars and just use:

gtk_label_set_line_wrap(label, TRUE);
gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_END);
gtk_label_set_lines(label, 2);

Take into account that if you want more precise control, you could even embed newlines in the text itself: the translators would eventually choose when and where to break.

Thanks, this works pretty nicely.

Sorry, the issue is different then I remembered it.

Indeed in the provided example I commented out the statement to enable wrapping, so it was fine that it did not wrap the label text. But when I enable wrapping I now get with latest GTK4:

$ ./label

(label:8776): Gtk-CRITICAL **: 12:13:15.138: Allocation height too small. Tried to allocate 306x140, but GtkApplicationWindow 0x55df177842a0 needs at least 306x177.

(label:8776): Gtk-CRITICAL **: 12:13:15.138: Allocation height too small. Tried to allocate 306x94, but GtkBox 0x55df177a6160 needs at least 306x131.

Program is

$ cat label.nim 
import gintro/[gtk4, gobject, gio]

proc toBoolVal(b: bool): Value =
  let gtype = typeFromName("gboolean")
  discard init(result, gtype)
  setBoolean(result, b)

proc activate(app: gtk4.Application) =
  let d = gtk4.getDefaultSettings()
  setProperty(d, "gtk-application-prefer-dark-theme", toBoolVal(true))
  let window = newApplicationWindow(app)
  window.title = "Window"
  window.defaultSize = (100, 20)
  let box = newBox(Orientation.vertical, 20)
  window.setChild( box)
  let label1 = newLabel("This text does not wrap")
  let label2 = newLabel("But this very long text can wrap automatically")
  label2.setWrap(true)
  #label2.setProperty("wrap", toBoolVal(true))
  box.append(label1)
  box.append(label2)
  window.show

proc main =
  let app = newApplication("org.gtk.example")
  app.connect("activate", activate)
  let status = app.run
  quit(status)

main()

Of course the window default size is too small, but shall that give a critical error? I think with old GTK 3.97 there was no error.

Lots of information about label sizing can be found here: HowDoI/Labels - GNOME Wiki!

To answer a question: yes, ‘characters’ is always Unicode characters, not bytes. But the width that is
used for this is the average glyph width, so you may not get the exact number of characters you asked for.

1 Like

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