Skip to main content

markdown_editor/
style.rs

1use gpui::{Hsla, Pixels};
2
3use gpui_kit::base::SemanticThemeTokens;
4
5/// Presentation seam for [`super::BlockEditor`]. Private fields, `with_*`
6/// setters and readers (ARCHITECTURE.md invariant 12). Unset colours are
7/// transparent and are filled from the theme tokens by [`Self::resolved`],
8/// mirroring `InputEditorStyle::resolved`.
9#[derive(Clone, Debug, PartialEq)]
10pub struct BlockEditorStyle {
11    foreground: Hsla,
12    muted_foreground: Hsla,
13    caret: Hsla,
14    caret_width: Pixels,
15    selection: Hsla,
16    composition_underline: Hsla,
17}
18
19impl Default for BlockEditorStyle {
20    fn default() -> Self {
21        let unset = Hsla::transparent_black();
22        Self {
23            foreground: unset,
24            muted_foreground: unset,
25            caret: unset,
26            caret_width: crate::support::CURSOR_WIDTH,
27            selection: unset,
28            composition_underline: unset,
29        }
30    }
31}
32
33macro_rules! style_field {
34    ($with:ident, $get:ident, $ty:ty) => {
35        pub fn $with(mut self, value: $ty) -> Self {
36            self.$get = value;
37            self
38        }
39        pub fn $get(&self) -> $ty {
40            self.$get
41        }
42    };
43}
44
45impl BlockEditorStyle {
46    style_field!(with_foreground, foreground, Hsla);
47    style_field!(with_muted_foreground, muted_foreground, Hsla);
48    style_field!(with_caret, caret, Hsla);
49    style_field!(with_caret_width, caret_width, Pixels);
50    style_field!(with_selection, selection, Hsla);
51    style_field!(with_composition_underline, composition_underline, Hsla);
52
53    /// Whether no selection colour was set, so the view uses the text
54    /// renderer's own (`TextViewStyle::selection`).
55    pub(crate) fn selection_is_default(&self) -> bool {
56        self.selection.a == 0.
57    }
58
59    /// Fill unset colours from the active palette.
60    pub fn resolved(&self, tokens: &SemanticThemeTokens) -> Self {
61        let colors = &tokens.colors;
62        let or = |value: Hsla, fallback: Hsla| if value.a == 0. { fallback } else { value };
63        let foreground = or(self.foreground, colors.foreground);
64        Self {
65            foreground,
66            muted_foreground: or(self.muted_foreground, colors.muted_foreground),
67            caret: or(self.caret, foreground),
68            composition_underline: or(self.composition_underline, foreground),
69            ..self.clone()
70        }
71    }
72}