Cargo.lock 🔗
@@ -9586,7 +9586,11 @@ version = "0.1.0"
dependencies = [
"command_palette_hooks",
"feature_flags",
+ "fs",
"gpui",
+ "project",
+ "settings",
+ "theme",
"ui",
"workspace",
]
Marshall Bowers created
This PR adds a prototype for controlling settings via the settings UI.
Still staff-shipped.
Release Notes:
- N/A
Cargo.lock | 4
crates/settings_ui/Cargo.toml | 4
crates/settings_ui/src/settings_ui.rs | 11 +
crates/settings_ui/src/theme_settings_ui.rs | 190 +++++++++++++++++++++++
4 files changed, 208 insertions(+), 1 deletion(-)
@@ -9586,7 +9586,11 @@ version = "0.1.0"
dependencies = [
"command_palette_hooks",
"feature_flags",
+ "fs",
"gpui",
+ "project",
+ "settings",
+ "theme",
"ui",
"workspace",
]
@@ -14,6 +14,10 @@ path = "src/settings_ui.rs"
[dependencies]
command_palette_hooks.workspace = true
feature_flags.workspace = true
+fs.workspace = true
gpui.workspace = true
+project.workspace = true
+settings.workspace = true
+theme.workspace = true
ui.workspace = true
workspace.workspace = true
@@ -1,3 +1,5 @@
+mod theme_settings_ui;
+
use std::any::TypeId;
use command_palette_hooks::CommandPaletteFilter;
@@ -7,6 +9,10 @@ use ui::prelude::*;
use workspace::item::{Item, ItemEvent};
use workspace::Workspace;
+use crate::theme_settings_ui::{
+ BufferFontSizeSetting, EditableSetting, InlineGitBlameSetting, UiFontSizeSetting,
+};
+
pub struct SettingsUiFeatureFlag;
impl FeatureFlag for SettingsUiFeatureFlag {
@@ -95,7 +101,7 @@ impl Item for SettingsPage {
}
impl Render for SettingsPage {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
v_flex()
.p_4()
.size_full()
@@ -103,5 +109,8 @@ impl Render for SettingsPage {
.child(Label::new(
"Nothing to see here yet. Feature-flagged for staff.",
))
+ .child(UiFontSizeSetting::new(cx))
+ .child(BufferFontSizeSetting::new(cx))
+ .child(InlineGitBlameSetting::new(cx))
}
}
@@ -0,0 +1,190 @@
+use fs::Fs;
+use gpui::AppContext;
+use project::project_settings::{InlineBlameSettings, ProjectSettings};
+use settings::{update_settings_file, Settings};
+use theme::ThemeSettings;
+use ui::{prelude::*, CheckboxWithLabel, NumericStepper};
+
+pub trait EditableSetting: RenderOnce {
+ /// The type of the setting value.
+ type Value: Send;
+
+ /// The settings type to which this setting belongs.
+ type Settings: Settings;
+
+ /// Returns the name of this setting.
+ fn name(&self) -> SharedString;
+
+ /// Returns the icon to be displayed in place of the setting name.
+ fn icon(&self) -> Option<IconName> {
+ None
+ }
+
+ /// Returns a new instance of this setting.
+ fn new(cx: &AppContext) -> Self;
+
+ /// Applies the given setting file to the settings file contents.
+ ///
+ /// This will be called when writing the setting value back to the settings file.
+ fn apply(settings: &mut <Self::Settings as Settings>::FileContent, value: Self::Value);
+
+ /// Writes the given setting value to the settings files.
+ fn write(value: Self::Value, cx: &AppContext) {
+ let fs = <dyn Fs>::global(cx);
+
+ update_settings_file::<Self::Settings>(fs, cx, move |settings, _cx| {
+ Self::apply(settings, value);
+ });
+ }
+}
+
+#[derive(IntoElement)]
+pub struct UiFontSizeSetting(Pixels);
+
+impl EditableSetting for UiFontSizeSetting {
+ type Value = Pixels;
+ type Settings = ThemeSettings;
+
+ fn name(&self) -> SharedString {
+ "UI Font Size".into()
+ }
+
+ fn icon(&self) -> Option<IconName> {
+ Some(IconName::FontSize)
+ }
+
+ fn new(cx: &AppContext) -> Self {
+ let settings = ThemeSettings::get_global(cx);
+
+ Self(settings.ui_font_size)
+ }
+
+ fn apply(settings: &mut <Self::Settings as Settings>::FileContent, value: Self::Value) {
+ settings.ui_font_size = Some(value.into());
+ }
+}
+
+impl RenderOnce for UiFontSizeSetting {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ let value = self.0;
+
+ h_flex()
+ .gap_2()
+ .map(|el| {
+ if let Some(icon) = self.icon() {
+ el.child(Icon::new(icon))
+ } else {
+ el.child(Label::new(self.name()))
+ }
+ })
+ .child(NumericStepper::new(
+ self.0.to_string(),
+ move |_, cx| {
+ Self::write(value - px(1.), cx);
+ },
+ move |_, cx| {
+ Self::write(value + px(1.), cx);
+ },
+ ))
+ }
+}
+
+#[derive(IntoElement)]
+pub struct BufferFontSizeSetting(Pixels);
+
+impl EditableSetting for BufferFontSizeSetting {
+ type Value = Pixels;
+ type Settings = ThemeSettings;
+
+ fn name(&self) -> SharedString {
+ "Buffer Font Size".into()
+ }
+
+ fn icon(&self) -> Option<IconName> {
+ Some(IconName::FontSize)
+ }
+
+ fn new(cx: &AppContext) -> Self {
+ let settings = ThemeSettings::get_global(cx);
+
+ Self(settings.buffer_font_size)
+ }
+
+ fn apply(settings: &mut <Self::Settings as Settings>::FileContent, value: Self::Value) {
+ settings.buffer_font_size = Some(value.into());
+ }
+}
+
+impl RenderOnce for BufferFontSizeSetting {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ let value = self.0;
+
+ h_flex()
+ .gap_2()
+ .map(|el| {
+ if let Some(icon) = self.icon() {
+ el.child(Icon::new(icon))
+ } else {
+ el.child(Label::new(self.name()))
+ }
+ })
+ .child(NumericStepper::new(
+ self.0.to_string(),
+ move |_, cx| {
+ Self::write(value - px(1.), cx);
+ },
+ move |_, cx| {
+ Self::write(value + px(1.), cx);
+ },
+ ))
+ }
+}
+
+#[derive(IntoElement)]
+pub struct InlineGitBlameSetting(bool);
+
+impl EditableSetting for InlineGitBlameSetting {
+ type Value = bool;
+ type Settings = ProjectSettings;
+
+ fn name(&self) -> SharedString {
+ "Inline Git Blame".into()
+ }
+
+ fn new(cx: &AppContext) -> Self {
+ let settings = ProjectSettings::get_global(cx);
+ Self(settings.git.inline_blame_enabled())
+ }
+
+ fn apply(settings: &mut <Self::Settings as Settings>::FileContent, value: Self::Value) {
+ if let Some(inline_blame) = settings.git.inline_blame.as_mut() {
+ inline_blame.enabled = value;
+ } else {
+ settings.git.inline_blame = Some(InlineBlameSettings {
+ enabled: false,
+ ..Default::default()
+ });
+ }
+ }
+}
+
+impl RenderOnce for InlineGitBlameSetting {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ let value = self.0;
+
+ CheckboxWithLabel::new(
+ "inline-git-blame",
+ Label::new(self.name()),
+ value.into(),
+ |selection, cx| {
+ Self::write(
+ match selection {
+ Selection::Selected => true,
+ Selection::Unselected | Selection::Indeterminate => false,
+ },
+ cx,
+ );
+ },
+ )
+ }
+}