editing_page.rs

  1use editor::{EditorSettings, ShowMinimap};
  2use fs::Fs;
  3use gpui::{Action, App, IntoElement, Pixels, Window};
  4use language::language_settings::AllLanguageSettings;
  5use project::project_settings::ProjectSettings;
  6use settings::{Settings as _, update_settings_file};
  7use theme::{FontFamilyCache, FontFamilyName, ThemeSettings};
  8use ui::{
  9    Clickable, ContextMenu, DropdownMenu, IconButton, Label, LabelCommon, LabelSize,
 10    NumericStepper, ParentElement, SharedString, Styled, SwitchColor, SwitchField,
 11    ToggleButtonGroup, ToggleButtonGroupStyle, ToggleButtonSimple, ToggleState, div, h_flex, px,
 12    v_flex,
 13};
 14
 15use crate::{ImportCursorSettings, ImportVsCodeSettings};
 16
 17fn read_show_mini_map(cx: &App) -> ShowMinimap {
 18    editor::EditorSettings::get_global(cx).minimap.show
 19}
 20
 21fn write_show_mini_map(show: ShowMinimap, cx: &mut App) {
 22    let fs = <dyn Fs>::global(cx);
 23
 24    update_settings_file::<EditorSettings>(fs, cx, move |editor_settings, _| {
 25        editor_settings.minimap.get_or_insert_default().show = Some(show);
 26    });
 27}
 28
 29fn read_inlay_hints(cx: &App) -> bool {
 30    AllLanguageSettings::get_global(cx)
 31        .defaults
 32        .inlay_hints
 33        .enabled
 34}
 35
 36fn write_inlay_hints(enabled: bool, cx: &mut App) {
 37    let fs = <dyn Fs>::global(cx);
 38
 39    update_settings_file::<AllLanguageSettings>(fs, cx, move |all_language_settings, cx| {
 40        all_language_settings
 41            .defaults
 42            .inlay_hints
 43            .get_or_insert_with(|| {
 44                AllLanguageSettings::get_global(cx)
 45                    .clone()
 46                    .defaults
 47                    .inlay_hints
 48            })
 49            .enabled = enabled;
 50    });
 51}
 52
 53fn read_git_blame(cx: &App) -> bool {
 54    ProjectSettings::get_global(cx).git.inline_blame_enabled()
 55}
 56
 57fn set_git_blame(enabled: bool, cx: &mut App) {
 58    let fs = <dyn Fs>::global(cx);
 59
 60    update_settings_file::<ProjectSettings>(fs, cx, move |project_settings, _| {
 61        project_settings
 62            .git
 63            .inline_blame
 64            .get_or_insert_default()
 65            .enabled = enabled;
 66    });
 67}
 68
 69fn write_ui_font_family(font: SharedString, cx: &mut App) {
 70    let fs = <dyn Fs>::global(cx);
 71
 72    update_settings_file::<ThemeSettings>(fs, cx, move |theme_settings, _| {
 73        theme_settings.ui_font_family = Some(FontFamilyName(font.into()));
 74    });
 75}
 76
 77fn write_ui_font_size(size: Pixels, cx: &mut App) {
 78    let fs = <dyn Fs>::global(cx);
 79
 80    update_settings_file::<ThemeSettings>(fs, cx, move |theme_settings, _| {
 81        theme_settings.ui_font_size = Some(size.into());
 82    });
 83}
 84
 85fn write_buffer_font_size(size: Pixels, cx: &mut App) {
 86    let fs = <dyn Fs>::global(cx);
 87
 88    update_settings_file::<ThemeSettings>(fs, cx, move |theme_settings, _| {
 89        theme_settings.buffer_font_size = Some(size.into());
 90    });
 91}
 92
 93fn write_buffer_font_family(font_family: SharedString, cx: &mut App) {
 94    let fs = <dyn Fs>::global(cx);
 95
 96    update_settings_file::<ThemeSettings>(fs, cx, move |theme_settings, _| {
 97        theme_settings.buffer_font_family = Some(FontFamilyName(font_family.into()));
 98    });
 99}
100
101pub(crate) fn render_editing_page(window: &mut Window, cx: &mut App) -> impl IntoElement {
102    let theme_settings = ThemeSettings::get_global(cx);
103    let ui_font_size = theme_settings.ui_font_size(cx);
104    let font_family = theme_settings.buffer_font.family.clone();
105    let buffer_font_size = theme_settings.buffer_font_size(cx);
106
107    v_flex()
108        .gap_4()
109        .child(Label::new("Import Settings").size(LabelSize::Large))
110        .child(
111            Label::new("Automatically pull your settings from other editors.")
112                .size(LabelSize::Small),
113        )
114        .child(
115            h_flex()
116                .child(
117                    IconButton::new("import-vs-code-settings", ui::IconName::Code).on_click(
118                        |_, window, cx| {
119                            window
120                                .dispatch_action(ImportVsCodeSettings::default().boxed_clone(), cx)
121                        },
122                    ),
123                )
124                .child(
125                    IconButton::new("import-cursor-settings", ui::IconName::CursorIBeam).on_click(
126                        |_, window, cx| {
127                            window
128                                .dispatch_action(ImportCursorSettings::default().boxed_clone(), cx)
129                        },
130                    ),
131                ),
132        )
133        .child(Label::new("Popular Settings").size(LabelSize::Large))
134        .child(
135            h_flex()
136                .gap_4()
137                .justify_between()
138                .child(
139                    v_flex()
140                        .justify_between()
141                        .gap_1()
142                        .child(Label::new("UI Font"))
143                        .child(
144                            h_flex()
145                                .justify_between()
146                                .gap_2()
147                                .child(div().min_w(px(120.)).child(DropdownMenu::new(
148                                    "ui-font-family",
149                                    theme_settings.ui_font.family.clone(),
150                                    ContextMenu::build(window, cx, |mut menu, _, cx| {
151                                        let font_family_cache = FontFamilyCache::global(cx);
152
153                                        for font_name in font_family_cache.list_font_families(cx) {
154                                            menu = menu.custom_entry(
155                                                {
156                                                    let font_name = font_name.clone();
157                                                    move |_window, _cx| {
158                                                        Label::new(font_name.clone())
159                                                            .into_any_element()
160                                                    }
161                                                },
162                                                {
163                                                    let font_name = font_name.clone();
164                                                    move |_window, cx| {
165                                                        write_ui_font_family(font_name.clone(), cx);
166                                                    }
167                                                },
168                                            )
169                                        }
170
171                                        menu
172                                    }),
173                                )))
174                                .child(NumericStepper::new(
175                                    "ui-font-size",
176                                    ui_font_size.to_string(),
177                                    move |_, _, cx| {
178                                        write_ui_font_size(ui_font_size - px(1.), cx);
179                                    },
180                                    move |_, _, cx| {
181                                        write_ui_font_size(ui_font_size + px(1.), cx);
182                                    },
183                                )),
184                        ),
185                )
186                .child(
187                    v_flex()
188                        .justify_between()
189                        .gap_1()
190                        .child(Label::new("Editor Font"))
191                        .child(
192                            h_flex()
193                                .justify_between()
194                                .gap_2()
195                                .child(DropdownMenu::new(
196                                    "buffer-font-family",
197                                    font_family,
198                                    ContextMenu::build(window, cx, |mut menu, _, cx| {
199                                        let font_family_cache = FontFamilyCache::global(cx);
200
201                                        for font_name in font_family_cache.list_font_families(cx) {
202                                            menu = menu.custom_entry(
203                                                {
204                                                    let font_name = font_name.clone();
205                                                    move |_window, _cx| {
206                                                        Label::new(font_name.clone())
207                                                            .into_any_element()
208                                                    }
209                                                },
210                                                {
211                                                    let font_name = font_name.clone();
212                                                    move |_window, cx| {
213                                                        write_buffer_font_family(
214                                                            font_name.clone(),
215                                                            cx,
216                                                        );
217                                                    }
218                                                },
219                                            )
220                                        }
221
222                                        menu
223                                    }),
224                                ))
225                                .child(NumericStepper::new(
226                                    "buffer-font-size",
227                                    buffer_font_size.to_string(),
228                                    move |_, _, cx| {
229                                        write_buffer_font_size(buffer_font_size - px(1.), cx);
230                                    },
231                                    move |_, _, cx| {
232                                        write_buffer_font_size(buffer_font_size + px(1.), cx);
233                                    },
234                                )),
235                        ),
236                ),
237        )
238        .child(
239            h_flex()
240                .justify_between()
241                .child(Label::new("Mini Map"))
242                .child(
243                    ToggleButtonGroup::single_row(
244                        "onboarding-show-mini-map",
245                        [
246                            ToggleButtonSimple::new("Auto", |_, _, cx| {
247                                write_show_mini_map(ShowMinimap::Auto, cx);
248                            }),
249                            ToggleButtonSimple::new("Always", |_, _, cx| {
250                                write_show_mini_map(ShowMinimap::Always, cx);
251                            }),
252                            ToggleButtonSimple::new("Never", |_, _, cx| {
253                                write_show_mini_map(ShowMinimap::Never, cx);
254                            }),
255                        ],
256                    )
257                    .selected_index(match read_show_mini_map(cx) {
258                        ShowMinimap::Auto => 0,
259                        ShowMinimap::Always => 1,
260                        ShowMinimap::Never => 2,
261                    })
262                    .style(ToggleButtonGroupStyle::Outlined)
263                    .button_width(ui::rems_from_px(64.)),
264                ),
265        )
266        .child(
267            SwitchField::new(
268                "onboarding-enable-inlay-hints",
269                "Inlay Hints",
270                "See parameter names for function and method calls inline.",
271                if read_inlay_hints(cx) {
272                    ui::ToggleState::Selected
273                } else {
274                    ui::ToggleState::Unselected
275                },
276                |toggle_state, _, cx| {
277                    write_inlay_hints(toggle_state == &ToggleState::Selected, cx);
278                },
279            )
280            .color(SwitchColor::Accent),
281        )
282        .child(
283            SwitchField::new(
284                "onboarding-git-blame-switch",
285                "Git Blame",
286                "See who committed each line on a given file.",
287                if read_git_blame(cx) {
288                    ui::ToggleState::Selected
289                } else {
290                    ui::ToggleState::Unselected
291                },
292                |toggle_state, _, cx| {
293                    set_git_blame(toggle_state == &ToggleState::Selected, cx);
294                },
295            )
296            .color(SwitchColor::Accent),
297        )
298}