editor_settings_controls.rs

  1use gpui::{AppContext, FontWeight};
  2use project::project_settings::{InlineBlameSettings, ProjectSettings};
  3use settings::{EditableSettingControl, Settings};
  4use theme::ThemeSettings;
  5use ui::{
  6    prelude::*, CheckboxWithLabel, ContextMenu, DropdownMenu, NumericStepper, SettingsContainer,
  7    SettingsGroup,
  8};
  9
 10#[derive(IntoElement)]
 11pub struct EditorSettingsControls {}
 12
 13impl EditorSettingsControls {
 14    pub fn new() -> Self {
 15        Self {}
 16    }
 17}
 18
 19impl RenderOnce for EditorSettingsControls {
 20    fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
 21        SettingsContainer::new()
 22            .child(
 23                SettingsGroup::new("Font")
 24                    .child(BufferFontSizeControl)
 25                    .child(BufferFontWeightControl),
 26            )
 27            .child(SettingsGroup::new("Editor").child(InlineGitBlameControl))
 28    }
 29}
 30
 31#[derive(IntoElement)]
 32struct BufferFontSizeControl;
 33
 34impl EditableSettingControl for BufferFontSizeControl {
 35    type Value = Pixels;
 36    type Settings = ThemeSettings;
 37
 38    fn name(&self) -> SharedString {
 39        "Buffer Font Size".into()
 40    }
 41
 42    fn read(cx: &AppContext) -> Self::Value {
 43        let settings = ThemeSettings::get_global(cx);
 44        settings.buffer_font_size
 45    }
 46
 47    fn apply(
 48        settings: &mut <Self::Settings as Settings>::FileContent,
 49        value: Self::Value,
 50        _cx: &AppContext,
 51    ) {
 52        settings.buffer_font_size = Some(value.into());
 53    }
 54}
 55
 56impl RenderOnce for BufferFontSizeControl {
 57    fn render(self, cx: &mut WindowContext) -> impl IntoElement {
 58        let value = Self::read(cx);
 59
 60        h_flex()
 61            .gap_2()
 62            .child(Icon::new(IconName::FontSize))
 63            .child(NumericStepper::new(
 64                value.to_string(),
 65                move |_, cx| {
 66                    Self::write(value - px(1.), cx);
 67                },
 68                move |_, cx| {
 69                    Self::write(value + px(1.), cx);
 70                },
 71            ))
 72    }
 73}
 74
 75#[derive(IntoElement)]
 76struct BufferFontWeightControl;
 77
 78impl EditableSettingControl for BufferFontWeightControl {
 79    type Value = FontWeight;
 80    type Settings = ThemeSettings;
 81
 82    fn name(&self) -> SharedString {
 83        "Buffer Font Weight".into()
 84    }
 85
 86    fn read(cx: &AppContext) -> Self::Value {
 87        let settings = ThemeSettings::get_global(cx);
 88        settings.buffer_font.weight
 89    }
 90
 91    fn apply(
 92        settings: &mut <Self::Settings as Settings>::FileContent,
 93        value: Self::Value,
 94        _cx: &AppContext,
 95    ) {
 96        settings.buffer_font_weight = Some(value.0);
 97    }
 98}
 99
100impl RenderOnce for BufferFontWeightControl {
101    fn render(self, cx: &mut WindowContext) -> impl IntoElement {
102        let value = Self::read(cx);
103
104        h_flex()
105            .gap_2()
106            .child(Icon::new(IconName::FontWeight))
107            .child(DropdownMenu::new(
108                "buffer-font-weight",
109                value.0.to_string(),
110                ContextMenu::build(cx, |mut menu, _cx| {
111                    for weight in FontWeight::ALL {
112                        menu = menu.custom_entry(
113                            move |_cx| Label::new(weight.0.to_string()).into_any_element(),
114                            {
115                                move |cx| {
116                                    Self::write(weight, cx);
117                                }
118                            },
119                        )
120                    }
121
122                    menu
123                }),
124            ))
125    }
126}
127
128#[derive(IntoElement)]
129struct InlineGitBlameControl;
130
131impl EditableSettingControl for InlineGitBlameControl {
132    type Value = bool;
133    type Settings = ProjectSettings;
134
135    fn name(&self) -> SharedString {
136        "Inline Git Blame".into()
137    }
138
139    fn read(cx: &AppContext) -> Self::Value {
140        let settings = ProjectSettings::get_global(cx);
141        settings.git.inline_blame_enabled()
142    }
143
144    fn apply(
145        settings: &mut <Self::Settings as Settings>::FileContent,
146        value: Self::Value,
147        _cx: &AppContext,
148    ) {
149        if let Some(inline_blame) = settings.git.inline_blame.as_mut() {
150            inline_blame.enabled = value;
151        } else {
152            settings.git.inline_blame = Some(InlineBlameSettings {
153                enabled: false,
154                ..Default::default()
155            });
156        }
157    }
158}
159
160impl RenderOnce for InlineGitBlameControl {
161    fn render(self, cx: &mut WindowContext) -> impl IntoElement {
162        let value = Self::read(cx);
163
164        CheckboxWithLabel::new(
165            "inline-git-blame",
166            Label::new(self.name()),
167            value.into(),
168            |selection, cx| {
169                Self::write(
170                    match selection {
171                        Selection::Selected => true,
172                        Selection::Unselected | Selection::Indeterminate => false,
173                    },
174                    cx,
175                );
176            },
177        )
178    }
179}