editing_page.rs

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