Skip to main content

fresh/app/types/
theme.rs

1/// Lightweight per-cell theme key provenance recorded during rendering.
2/// Stored in `ChromeLayout::cell_theme_map` so the theme inspector popup
3/// can look up the exact keys used for any screen position.
4///
5/// Keys are `Cow<'static, str>` so the hot editor/chrome paths store cheap
6/// borrowed `&'static str` literals while plugin-driven surfaces (the
7/// orchestrator dock) can record the runtime key strings their text
8/// properties carry.
9#[derive(Debug, Clone, Default)]
10pub struct CellThemeInfo {
11    /// Foreground theme key (e.g. "syntax.keyword", "editor.fg")
12    pub fg_key: Option<std::borrow::Cow<'static, str>>,
13    /// Background theme key (e.g. "editor.bg", "diagnostic.warning_bg")
14    pub bg_key: Option<std::borrow::Cow<'static, str>>,
15    /// Short region label (e.g. "Line Numbers", "Editor Content")
16    pub region: std::borrow::Cow<'static, str>,
17    /// Dynamic region suffix (e.g. syntax category display name appended to "Syntax: ")
18    pub syntax_category: Option<std::borrow::Cow<'static, str>>,
19}
20
21/// One horizontal run of cells a chrome renderer painted with a known set of
22/// theme keys, captured *as it paints*. Renderers collect these into a fresh
23/// `Vec` (sidestepping any borrow of the per-cell map / the window) and the
24/// caller applies them via [`ChromeLayout::apply_theme_runs`] once its own
25/// borrows are released. Keys are `&'static str` (all chrome keys are literals).
26#[derive(Debug, Clone, Copy)]
27pub struct ThemeRun {
28    pub x: u16,
29    pub y: u16,
30    pub w: u16,
31    pub fg_key: Option<&'static str>,
32    pub bg_key: Option<&'static str>,
33    pub region: &'static str,
34}
35
36/// Write theme-key runs into a flat per-cell map of the given `width` (rows
37/// indexed `row * width + col`). Cells outside the frame are skipped. Used by
38/// both [`super::layout::ChromeLayout::apply_theme_runs`] and the split
39/// rendering pipeline, which holds the map directly.
40pub fn apply_theme_runs(map: &mut [CellThemeInfo], width: u16, runs: &[ThemeRun]) {
41    use std::borrow::Cow;
42    if width == 0 {
43        return;
44    }
45    let stride = width as usize;
46    for r in runs {
47        for col in r.x..r.x.saturating_add(r.w) {
48            if col >= width {
49                break;
50            }
51            let idx = r.y as usize * stride + col as usize;
52            if let Some(cell) = map.get_mut(idx) {
53                cell.fg_key = r.fg_key.map(Cow::Borrowed);
54                cell.bg_key = r.bg_key.map(Cow::Borrowed);
55                cell.region = Cow::Borrowed(r.region);
56                cell.syntax_category = None;
57            }
58        }
59    }
60}
61
62/// Collects [`ThemeRun`]s during a chrome region's paint. Threaded as
63/// `Option<&mut CellThemeRecorder>` so recording is opt-in (the inspector
64/// wants it; offscreen/test renders pass `None`).
65pub struct CellThemeRecorder<'a> {
66    runs: &'a mut Vec<ThemeRun>,
67}
68
69impl<'a> CellThemeRecorder<'a> {
70    pub fn new(runs: &'a mut Vec<ThemeRun>) -> Self {
71        Self { runs }
72    }
73
74    /// Record a horizontal run of `w` cells starting at screen `(x, y)`.
75    pub fn run(
76        &mut self,
77        x: u16,
78        y: u16,
79        w: u16,
80        fg_key: Option<&'static str>,
81        bg_key: Option<&'static str>,
82        region: &'static str,
83    ) {
84        if w == 0 {
85            return;
86        }
87        self.runs.push(ThemeRun {
88            x,
89            y,
90            w,
91            fg_key,
92            bg_key,
93            region,
94        });
95    }
96}
97
98/// Information about which theme key(s) style a specific screen position.
99/// Used by the Ctrl+Right-Click theme inspector popup.
100#[derive(Debug, Clone)]
101pub struct ThemeKeyInfo {
102    /// The foreground theme key path (e.g., "syntax.keyword", "editor.fg")
103    pub fg_key: Option<String>,
104    /// The background theme key path (e.g., "editor.bg", "editor.selection_bg")
105    pub bg_key: Option<String>,
106    /// Human-readable description of the UI region
107    pub region: String,
108    /// The actual foreground color value currently applied
109    pub fg_color: Option<ratatui::style::Color>,
110    /// The actual background color value currently applied
111    pub bg_color: Option<ratatui::style::Color>,
112    /// For syntax highlights: the HighlightCategory display name
113    pub syntax_category: Option<String>,
114}
115
116/// State for the theme inspector popup (Ctrl+Right-Click)
117#[derive(Debug, Clone)]
118pub struct ThemeInfoPopup {
119    /// Screen position where popup appears (x, y)
120    pub position: (u16, u16),
121    /// Resolved theme key information
122    pub info: ThemeKeyInfo,
123    /// Whether the "Open in Theme Editor" button is highlighted (mouse hover)
124    pub button_highlighted: bool,
125}