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}