theme.rs

crates/veilvoice-gui/src/theme.rs

veilvoice-gui · 802 lines · read the source here · or on GitHub

Colour schemes for the desktop app.

One palette, three front-ends

Every theme here is the same set of twelve tokens the website defines in website/css/themes.css, with the same names and the same hex values, and Tokyo Night additionally matches the escape codes the CLI emits. The three front-ends are meant to read as one program rather than as three tools that happen to share a name, and the way that is kept true is by copying the numbers rather than by approximating them. Tests assert every token of every theme against the stylesheet, in both directions -- so a colour changed on either side, a theme removed from either side, or a theme added to the website and forgotten here all fail the build rather than shipping as two products that no longer look alike.

Why the active theme is an index, not a lock

Colours are read on every repaint, from the UI thread, dozens of times a frame. A Mutex around the palette would be a lock taken hundreds of times a second to read a constant, and a poisoned one would take the window with it. Instead the themes are a const array and the selection is a single AtomicUsize: reading is one relaxed load, it cannot fail, and it cannot be poisoned.

The index is clamped on read as well as on write. A value that somehow got out of range would otherwise panic on a slice index, in a paint loop, which is the worst possible place for it -- so the read saturates to the default instead.

In plain words

The colour schemes the application ships with, and the fonts.

They are the same schemes the website offers, defined once so the two cannot drift apart. Choosing one applies it straight away and it is remembered for next time.

WHAT THIS FILE CONTAINS

802 lines defining 9 functions (8 public), 1 type and 5 constants. Everything below is read out of the source, so it cannot disagree with the code.

The types it owns.

  • struct Theme line 54 · One complete colour scheme.

What happens when it runs. These are the ways in: public, and nothing else in this file calls them, so they are what an outside caller reaches first.

  • load_custom line 294 · Read the user's palettes and add them to the table.
  • set_by_id line 315 · Switch to id, and apply it to ctx.
    reaches by_id, install, themes, active
  • jetbrains_mono_path line 442 · Where JetBrains Mono is on this machine, if it is anywhere.
    reaches user_font_paths
  • install_fonts line 447 · Load JetBrains Mono if the system has it.
    reaches user_font_paths

WHAT CALLS WHAT

active line 264 themes line 281 load_custom line 294 by_id line 308 set_by_id line 315 user_font_paths line 420 jetbrains_mono_path line 442 install_fonts line 447 install line 471 entry: a way in: public, and nothing in this file calls it api: public, and also used inside this file helper: private to this file dashed: a call that goes back up, or across a wrapped rank The functions this file defines, and the calls between them. An edge means the callee's name appears, called, inside the caller's body. This is a syntactic reading, not a type-resolved one.

The functions this file defines, and the calls between them. An edge means the callee's name appears, called, inside the caller's body. This is a syntactic reading, not a type-resolved one.

The same graph as Mermaid source
%%{init: {"theme":"base","themeVariables":{"background":"#1a1b26","primaryColor":"#1f2335","primaryTextColor":"#c0caf5","primaryBorderColor":"#7aa2f7","secondaryColor":"#16161e","tertiaryColor":"#16161e","lineColor":"#737aa2","textColor":"#c0caf5","mainBkg":"#1f2335","nodeBorder":"#7aa2f7","clusterBkg":"#16161e","clusterBorder":"#2f3549","fontFamily":"ui-monospace, SFMono-Regular, Consolas, monospace","fontSize":"14px"}}}%%
flowchart TD
    n_active["active<br/>line 264"]
    n_themes["themes<br/>line 281"]
    n_load_custom(["load_custom<br/>line 294"])
    n_by_id["by_id<br/>line 308"]
    n_set_by_id(["set_by_id<br/>line 315"])
    n_user_font_paths["user_font_paths<br/>line 420"]
    n_jetbrains_mono_path(["jetbrains_mono_path<br/>line 442"])
    n_install_fonts(["install_fonts<br/>line 447"])
    n_install["install<br/>line 471"]
    n_active --> n_themes
    n_by_id --> n_themes
    n_install --> n_active
    n_install_fonts --> n_user_font_paths
    n_jetbrains_mono_path --> n_user_font_paths
    n_set_by_id --> n_by_id
    n_set_by_id --> n_install
    click n_active href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/theme.rs#L264" "open the source"
    click n_themes href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/theme.rs#L281" "open the source"
    click n_load_custom href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/theme.rs#L294" "open the source"
    click n_by_id href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/theme.rs#L308" "open the source"
    click n_set_by_id href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/theme.rs#L315" "open the source"
    click n_user_font_paths href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/theme.rs#L420" "open the source"
    click n_jetbrains_mono_path href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/theme.rs#L442" "open the source"
    click n_install_fonts href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/theme.rs#L447" "open the source"
    click n_install href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/theme.rs#L471" "open the source"
    classDef entry fill:#1f2335,stroke:#7aa2f7,color:#c0caf5
    class n_load_custom,n_set_by_id,n_jetbrains_mono_path,n_install_fonts entry
    classDef api fill:#1f2335,stroke:#7dcfff,color:#c0caf5
    class n_active,n_themes,n_by_id,n_install api
    classDef helper fill:#1f2335,stroke:#bb9af7,color:#c0caf5
    class n_user_font_paths helper

This site loads no third-party script, so it cannot run Mermaid; the diagram above is the same nodes and edges drawn by the generator instead. GitHub renders the source below directly.

ITEMS

ItemLineDocumentation
TABLE static47The theme table, once the user's palettes have been folded in.
Theme pub struct54One complete colour scheme.
fn const90
THEMES pub const101Every theme, in the order the picker shows them.
ACTIVE static258The index of the theme currently in force.
active pub fn264The theme currently in force.
themes pub fn281Every theme the picker offers: the built-in ones, then any the user added.
load_custom pub fn294Read the user's palettes and add them to the table.
by_id pub fn308Look a theme up by its stable identifier.
set_by_id pub fn315Switch to id, and apply it to ctx.
palette pub mod332Shorthand accessors, so call sites read as p::fg() rather than theme::active().fg.
JETBRAINS_MONO_PATHS const408Places JetBrains Mono is normally installed.
user_font_paths fn420
jetbrains_mono_path pub fn442Where JetBrains Mono is on this machine, if it is anywhere.
install_fonts pub fn447Load JetBrains Mono if the system has it.
install pub fn471Apply the active theme's visuals and a monospace-everywhere type scale.