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(settings: &mut <Self::Settings as Settings>::FileContent, value: Self::Value) {
 48        settings.buffer_font_size = Some(value.into());
 49    }
 50}
 51
 52impl RenderOnce for BufferFontSizeControl {
 53    fn render(self, cx: &mut WindowContext) -> impl IntoElement {
 54        let value = Self::read(cx);
 55
 56        h_flex()
 57            .gap_2()
 58            .child(Icon::new(IconName::FontSize))
 59            .child(NumericStepper::new(
 60                value.to_string(),
 61                move |_, cx| {
 62                    Self::write(value - px(1.), cx);
 63                },
 64                move |_, cx| {
 65                    Self::write(value + px(1.), cx);
 66                },
 67            ))
 68    }
 69}
 70
 71#[derive(IntoElement)]
 72struct BufferFontWeightControl;
 73
 74impl EditableSettingControl for BufferFontWeightControl {
 75    type Value = FontWeight;
 76    type Settings = ThemeSettings;
 77
 78    fn name(&self) -> SharedString {
 79        "Buffer Font Weight".into()
 80    }
 81
 82    fn read(cx: &AppContext) -> Self::Value {
 83        let settings = ThemeSettings::get_global(cx);
 84        settings.buffer_font.weight
 85    }
 86
 87    fn apply(settings: &mut <Self::Settings as Settings>::FileContent, value: Self::Value) {
 88        settings.buffer_font_weight = Some(value.0);
 89    }
 90}
 91
 92impl RenderOnce for BufferFontWeightControl {
 93    fn render(self, cx: &mut WindowContext) -> impl IntoElement {
 94        let value = Self::read(cx);
 95
 96        h_flex()
 97            .gap_2()
 98            .child(Icon::new(IconName::FontWeight))
 99            .child(DropdownMenu::new(
100                "buffer-font-weight",
101                value.0.to_string(),
102                ContextMenu::build(cx, |mut menu, _cx| {
103                    for weight in FontWeight::ALL {
104                        menu = menu.custom_entry(
105                            move |_cx| Label::new(weight.0.to_string()).into_any_element(),
106                            {
107                                move |cx| {
108                                    Self::write(weight, cx);
109                                }
110                            },
111                        )
112                    }
113
114                    menu
115                }),
116            ))
117    }
118}
119
120#[derive(IntoElement)]
121struct InlineGitBlameControl;
122
123impl EditableSettingControl for InlineGitBlameControl {
124    type Value = bool;
125    type Settings = ProjectSettings;
126
127    fn name(&self) -> SharedString {
128        "Inline Git Blame".into()
129    }
130
131    fn read(cx: &AppContext) -> Self::Value {
132        let settings = ProjectSettings::get_global(cx);
133        settings.git.inline_blame_enabled()
134    }
135
136    fn apply(settings: &mut <Self::Settings as Settings>::FileContent, value: Self::Value) {
137        if let Some(inline_blame) = settings.git.inline_blame.as_mut() {
138            inline_blame.enabled = value;
139        } else {
140            settings.git.inline_blame = Some(InlineBlameSettings {
141                enabled: false,
142                ..Default::default()
143            });
144        }
145    }
146}
147
148impl RenderOnce for InlineGitBlameControl {
149    fn render(self, cx: &mut WindowContext) -> impl IntoElement {
150        let value = Self::read(cx);
151
152        CheckboxWithLabel::new(
153            "inline-git-blame",
154            Label::new(self.name()),
155            value.into(),
156            |selection, cx| {
157                Self::write(
158                    match selection {
159                        Selection::Selected => true,
160                        Selection::Unselected | Selection::Indeterminate => false,
161                    },
162                    cx,
163                );
164            },
165        )
166    }
167}