Theme font rendering

The customfontrenderer.C has some missing functionality with respect to LibCXXW's theming support. Specifying the font size in points computes the actual font size using the current LibCXXW display theme size, and it remains fixed at that size. Using the cxxwtheme utility to set a larger or a smaller display theme does not update the appearance of the custom widget until customfontrenderer gets stopped and restarted.

A modified example, customfontrenderer2.C, shows the additional steps required for adding proper theming support:

As a result of these additional steps, using cxxwtheme to set a new display theme size results in customfontrenderer2's window getting resized automatically.

Note

Specifying a font size in pixels generally means that the font's size does not depend on the display theme, and the font remains the same. This means that a new theme has no effect, and x;::w::current_fontcollection's x;::w::fontcollection remaining the same. customfontrenderer2 keeps track of the x;::w::fontcollection it's using, and only doing the extra work when it sees a new x;::w::fontcollection.

This extra work consists of calling load_glyphs() again. This is a new x;::w::fontcollection in town, and it needs to have its glyphs loaded, before they can get rendered, just like any other x;::w::fontcollection.

The x::themedim_elementObj template mixin.

customfontrenderer.C sets the size of the dropdown shadow to one-fifth the size of the font's height. customfontrenderer2.C takes a different approach, the x::w::themedim_elementObj. This is a template mixin that attaches a theme-based dimension (width or height) to a widget.

Instead of using one-fifth the size of the font's height, customfontrenderer2.C sets the shadow's size to 3.0 millimeters. customfontrenderer2.C gives an example of using the x::w::themedim_elementObj template mixin which normally computes a pixel size based on theme-specified dimension or display resolution that's equivalent to a given number of millimeters.

x::w::themedim_elementObj is a variadic template. This example uses it to attach only one dimension but it takes an optional list of class names that serves only as tags (the classes don't even need to be defined) and identifies each dimension by its class tag. x::w::themedim_elementObj's constructor takes a single parameter, a std::tuple with one value for each instantiated dimension. This example uses std::forward_as_tuple to forward a single value, shadow_init to the x::w::themedim_elementObj.

Typical implementation of custom theme-aware custom widgets

customfontrenderer2.C gives the general approach of implementing proper theme support with custom widgets:

  • Compute the custom widget's initial metrics before constructing it, and pass along the data that went into the calculations into the object. customfontrenderer2.C's computed metrics depend on a x;::w::fontcollection, The custom widget saves a private reference to this x;::w::fontcollection.

  • Both initialize() and theme_updated() recheck and update the saved data. A new x;::w::fontcollection results in the widget's metrics getting updated, together with any ancillary data that derived from it.