diff --git a/Cargo.lock b/Cargo.lock index 7f09342879..f171901e29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10942,9 +10942,12 @@ dependencies = [ "anyhow", "command_palette_hooks", "db", + "editor", "feature_flags", "fs", "gpui", + "language", + "project", "settings", "theme", "ui", diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 3c877873a0..a2f2310144 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -65,7 +65,7 @@ use display_map::*; pub use display_map::{ChunkRenderer, ChunkRendererContext, DisplayPoint, FoldPlaceholder}; pub use editor_settings::{ CurrentLineHighlight, DocumentColorsRenderMode, EditorSettings, HideMouseMode, - ScrollBeyondLastLine, ScrollbarAxes, SearchSettings, ShowScrollbar, + ScrollBeyondLastLine, ScrollbarAxes, SearchSettings, ShowMinimap, ShowScrollbar, }; use editor_settings::{GoToDefinitionFallback, Minimap as MinimapSettings}; pub use editor_settings_controls::*; diff --git a/crates/onboarding/Cargo.toml b/crates/onboarding/Cargo.toml index 6ec8f8b162..da009b4e4e 100644 --- a/crates/onboarding/Cargo.toml +++ b/crates/onboarding/Cargo.toml @@ -18,12 +18,15 @@ default = [] anyhow.workspace = true command_palette_hooks.workspace = true db.workspace = true +editor.workspace = true feature_flags.workspace = true fs.workspace = true gpui.workspace = true +language.workspace = true +project.workspace = true settings.workspace = true theme.workspace = true ui.workspace = true -workspace.workspace = true workspace-hack.workspace = true +workspace.workspace = true zed_actions.workspace = true diff --git a/crates/onboarding/src/editing_page.rs b/crates/onboarding/src/editing_page.rs new file mode 100644 index 0000000000..c07d8fef4d --- /dev/null +++ b/crates/onboarding/src/editing_page.rs @@ -0,0 +1,287 @@ +use editor::{EditorSettings, ShowMinimap}; +use fs::Fs; +use gpui::{App, IntoElement, Pixels, Window}; +use language::language_settings::AllLanguageSettings; +use project::project_settings::ProjectSettings; +use settings::{Settings as _, update_settings_file}; +use theme::{FontFamilyCache, FontFamilyName, ThemeSettings}; +use ui::{ + ContextMenu, DropdownMenu, IconButton, Label, LabelCommon, LabelSize, NumericStepper, + ParentElement, SharedString, Styled, SwitchColor, SwitchField, ToggleButtonGroup, + ToggleButtonGroupStyle, ToggleButtonSimple, ToggleState, div, h_flex, px, v_flex, +}; + +fn read_show_mini_map(cx: &App) -> ShowMinimap { + editor::EditorSettings::get_global(cx).minimap.show +} + +fn write_show_mini_map(show: ShowMinimap, cx: &mut App) { + let fs = ::global(cx); + + update_settings_file::(fs, cx, move |editor_settings, _| { + editor_settings.minimap.get_or_insert_default().show = Some(show); + }); +} + +fn read_inlay_hints(cx: &App) -> bool { + AllLanguageSettings::get_global(cx) + .defaults + .inlay_hints + .enabled +} + +fn write_inlay_hints(enabled: bool, cx: &mut App) { + let fs = ::global(cx); + + update_settings_file::(fs, cx, move |all_language_settings, cx| { + all_language_settings + .defaults + .inlay_hints + .get_or_insert_with(|| { + AllLanguageSettings::get_global(cx) + .clone() + .defaults + .inlay_hints + }) + .enabled = enabled; + }); +} + +fn read_git_blame(cx: &App) -> bool { + ProjectSettings::get_global(cx).git.inline_blame_enabled() +} + +fn set_git_blame(enabled: bool, cx: &mut App) { + let fs = ::global(cx); + + update_settings_file::(fs, cx, move |project_settings, _| { + project_settings + .git + .inline_blame + .get_or_insert_default() + .enabled = enabled; + }); +} + +fn write_ui_font_family(font: SharedString, cx: &mut App) { + let fs = ::global(cx); + + update_settings_file::(fs, cx, move |theme_settings, _| { + theme_settings.ui_font_family = Some(FontFamilyName(font.into())); + }); +} + +fn write_ui_font_size(size: Pixels, cx: &mut App) { + let fs = ::global(cx); + + update_settings_file::(fs, cx, move |theme_settings, _| { + theme_settings.ui_font_size = Some(size.into()); + }); +} + +fn write_buffer_font_size(size: Pixels, cx: &mut App) { + let fs = ::global(cx); + + update_settings_file::(fs, cx, move |theme_settings, _| { + theme_settings.buffer_font_size = Some(size.into()); + }); +} + +fn write_buffer_font_family(font_family: SharedString, cx: &mut App) { + let fs = ::global(cx); + + update_settings_file::(fs, cx, move |theme_settings, _| { + theme_settings.buffer_font_family = Some(FontFamilyName(font_family.into())); + }); +} + +pub(crate) fn render_editing_page(window: &mut Window, cx: &mut App) -> impl IntoElement { + let theme_settings = ThemeSettings::get_global(cx); + let ui_font_size = theme_settings.ui_font_size(cx); + let font_family = theme_settings.buffer_font.family.clone(); + let buffer_font_size = theme_settings.buffer_font_size(cx); + + v_flex() + .gap_4() + .child(Label::new("Import Settings").size(LabelSize::Large)) + .child( + Label::new("Automatically pull your settings from other editors.") + .size(LabelSize::Small), + ) + .child( + h_flex() + .child(IconButton::new( + "import-vs-code-settings", + ui::IconName::Code, + )) + .child(IconButton::new( + "import-cursor-settings", + ui::IconName::CursorIBeam, + )), + ) + .child(Label::new("Popular Settings").size(LabelSize::Large)) + .child( + h_flex() + .gap_4() + .justify_between() + .child( + v_flex() + .justify_between() + .gap_1() + .child(Label::new("UI Font")) + .child( + h_flex() + .justify_between() + .gap_2() + .child(div().min_w(px(120.)).child(DropdownMenu::new( + "ui-font-family", + theme_settings.ui_font.family.clone(), + ContextMenu::build(window, cx, |mut menu, _, cx| { + let font_family_cache = FontFamilyCache::global(cx); + + for font_name in font_family_cache.list_font_families(cx) { + menu = menu.custom_entry( + { + let font_name = font_name.clone(); + move |_window, _cx| { + Label::new(font_name.clone()) + .into_any_element() + } + }, + { + let font_name = font_name.clone(); + move |_window, cx| { + write_ui_font_family(font_name.clone(), cx); + } + }, + ) + } + + menu + }), + ))) + .child(NumericStepper::new( + "ui-font-size", + ui_font_size.to_string(), + move |_, _, cx| { + write_ui_font_size(ui_font_size - px(1.), cx); + }, + move |_, _, cx| { + write_ui_font_size(ui_font_size + px(1.), cx); + }, + )), + ), + ) + .child( + v_flex() + .justify_between() + .gap_1() + .child(Label::new("Editor Font")) + .child( + h_flex() + .justify_between() + .gap_2() + .child(DropdownMenu::new( + "buffer-font-family", + font_family, + ContextMenu::build(window, cx, |mut menu, _, cx| { + let font_family_cache = FontFamilyCache::global(cx); + + for font_name in font_family_cache.list_font_families(cx) { + menu = menu.custom_entry( + { + let font_name = font_name.clone(); + move |_window, _cx| { + Label::new(font_name.clone()) + .into_any_element() + } + }, + { + let font_name = font_name.clone(); + move |_window, cx| { + write_buffer_font_family( + font_name.clone(), + cx, + ); + } + }, + ) + } + + menu + }), + )) + .child(NumericStepper::new( + "buffer-font-size", + buffer_font_size.to_string(), + move |_, _, cx| { + write_buffer_font_size(buffer_font_size - px(1.), cx); + }, + move |_, _, cx| { + write_buffer_font_size(buffer_font_size + px(1.), cx); + }, + )), + ), + ), + ) + .child( + h_flex() + .justify_between() + .child(Label::new("Mini Map")) + .child( + ToggleButtonGroup::single_row( + "onboarding-show-mini-map", + [ + ToggleButtonSimple::new("Auto", |_, _, cx| { + write_show_mini_map(ShowMinimap::Auto, cx); + }), + ToggleButtonSimple::new("Always", |_, _, cx| { + write_show_mini_map(ShowMinimap::Always, cx); + }), + ToggleButtonSimple::new("Never", |_, _, cx| { + write_show_mini_map(ShowMinimap::Never, cx); + }), + ], + ) + .selected_index(match read_show_mini_map(cx) { + ShowMinimap::Auto => 0, + ShowMinimap::Always => 1, + ShowMinimap::Never => 2, + }) + .style(ToggleButtonGroupStyle::Outlined) + .button_width(ui::rems_from_px(64.)), + ), + ) + .child( + SwitchField::new( + "onboarding-enable-inlay-hints", + "Inlay Hints", + "See parameter names for function and method calls inline.", + if read_inlay_hints(cx) { + ui::ToggleState::Selected + } else { + ui::ToggleState::Unselected + }, + |toggle_state, _, cx| { + write_inlay_hints(toggle_state == &ToggleState::Selected, cx); + }, + ) + .color(SwitchColor::Accent), + ) + .child( + SwitchField::new( + "onboarding-git-blame-switch", + "Git Blame", + "See who committed each line on a given file.", + if read_git_blame(cx) { + ui::ToggleState::Selected + } else { + ui::ToggleState::Unselected + }, + |toggle_state, _, cx| { + set_git_blame(toggle_state == &ToggleState::Selected, cx); + }, + ) + .color(SwitchColor::Accent), + ) +} diff --git a/crates/onboarding/src/onboarding.rs b/crates/onboarding/src/onboarding.rs index b675ed2dd7..cc0c47ca71 100644 --- a/crates/onboarding/src/onboarding.rs +++ b/crates/onboarding/src/onboarding.rs @@ -21,6 +21,7 @@ use workspace::{ open_new, with_active_or_new_workspace, }; +mod editing_page; mod welcome; pub struct OnBoardingFeatureFlag {} @@ -246,7 +247,9 @@ impl Onboarding { fn render_page(&mut self, window: &mut Window, cx: &mut Context) -> AnyElement { match self.selected_page { SelectedPage::Basics => self.render_basics_page(window, cx).into_any_element(), - SelectedPage::Editing => self.render_editing_page(window, cx).into_any_element(), + SelectedPage::Editing => { + crate::editing_page::render_editing_page(window, cx).into_any_element() + } SelectedPage::AiSetup => self.render_ai_setup_page(window, cx).into_any_element(), } } @@ -281,11 +284,6 @@ impl Onboarding { ) } - fn render_editing_page(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { - // div().child("editing page") - "Right" - } - fn render_ai_setup_page(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { div().child("ai setup page") } diff --git a/crates/ui/src/components/numeric_stepper.rs b/crates/ui/src/components/numeric_stepper.rs index f9e6e88f01..05d368f427 100644 --- a/crates/ui/src/components/numeric_stepper.rs +++ b/crates/ui/src/components/numeric_stepper.rs @@ -2,7 +2,7 @@ use gpui::ClickEvent; use crate::{IconButtonShape, prelude::*}; -#[derive(IntoElement)] +#[derive(IntoElement, RegisterComponent)] pub struct NumericStepper { id: ElementId, value: SharedString, @@ -93,3 +93,34 @@ impl RenderOnce for NumericStepper { ) } } + +impl Component for NumericStepper { + fn scope() -> ComponentScope { + ComponentScope::Input + } + + fn name() -> &'static str { + "NumericStepper" + } + + fn sort_name() -> &'static str { + Self::name() + } + + fn description() -> Option<&'static str> { + Some("A button used to increment or decrement a numeric value. ") + } + + fn preview(_window: &mut Window, _cx: &mut App) -> Option { + Some( + div() + .child(NumericStepper::new( + "numeric-stepper-component-preview", + "10", + move |_, _, _| {}, + move |_, _, _| {}, + )) + .into_any_element(), + ) + } +}