Update approach to settings

Nate Butler and Marshall Bowers created

Co-Authored-By: Marshall Bowers <1486634+maxdeviant@users.noreply.github.com>

Change summary

crates/gpui3/src/styled.rs             |   8 +-
crates/ui2/src/components/list.rs      |   2 
crates/ui2/src/components/panel.rs     |   2 
crates/ui2/src/components/title_bar.rs |   2 
crates/ui2/src/elements/button.rs      |   5 
crates/ui2/src/prelude.rs              |   9 ++
crates/ui2/src/settings.rs             | 112 ++++++++++------------------
7 files changed, 58 insertions(+), 82 deletions(-)

Detailed changes

crates/gpui3/src/styled.rs 🔗

@@ -1,6 +1,6 @@
 use crate::{
-    self as gpui3, hsla, point, px, relative, rems, AbsoluteLength, AlignItems, Display, Fill,
-    FlexDirection, Hsla, JustifyContent, Length, Position, Rems, SharedString, StyleRefinement,
+    self as gpui3, hsla, point, px, relative, rems, AlignItems, Display, Fill, FlexDirection, Hsla,
+    JustifyContent, Length, Position, Rems, SharedString, StyleRefinement,
 };
 use crate::{BoxShadow, TextStyleRefinement};
 use smallvec::smallvec;
@@ -350,13 +350,13 @@ pub trait Styled {
         self
     }
 
-    fn text_size(mut self, size: Rems) -> Self
+    fn text_size(mut self, size: impl Into<Rems>) -> Self
     where
         Self: Sized,
     {
         self.text_style()
             .get_or_insert_with(Default::default)
-            .font_size = Some(size);
+            .font_size = Some(size.into());
         self
     }
 

crates/ui2/src/components/list.rs 🔗

@@ -405,7 +405,7 @@ impl<S: 'static + Send + Sync + Clone> ListEntry<S> {
                     // .ml(rems(0.75 * self.indent_level as f32))
                     .children((0..self.indent_level).map(|_| {
                         div()
-                            .w(setting.list_indent_depth())
+                            .w(*setting.list_indent_depth)
                             .h_full()
                             .flex()
                             .justify_center()

crates/ui2/src/components/panel.rs 🔗

@@ -61,7 +61,7 @@ impl<S: 'static + Send + Sync> Panel<S> {
             scroll_state,
             current_side: PanelSide::default(),
             allowed_sides: PanelAllowedSides::default(),
-            initial_width: setting.default_panel_size(),
+            initial_width: *setting.default_panel_size,
             width: None,
             children: SmallVec::new(),
         }

crates/ui2/src/components/title_bar.rs 🔗

@@ -126,7 +126,7 @@ impl TitleBar {
                             .flex()
                             .items_center()
                             .gap_1()
-                            .when(setting.titlebar_show_project_owner(), |this| {
+                            .when(*setting.titlebar.show_project_owner, |this| {
                                 this.child(Button::new("iamnbutler"))
                             })
                             .child(Button::new("zed"))

crates/ui2/src/elements/button.rs 🔗

@@ -1,7 +1,8 @@
 use std::marker::PhantomData;
 use std::sync::Arc;
 
-use gpui3::{rems, DefiniteLength, Hsla, Interactive, MouseButton, WindowContext};
+use gpui3::rems;
+use gpui3::{DefiniteLength, Hsla, Interactive, MouseButton, WindowContext};
 
 use crate::prelude::*;
 use crate::settings::user_settings;
@@ -153,7 +154,7 @@ impl<S: 'static + Send + Sync + Clone> Button<S> {
 
         let mut el = h_stack()
             .p_1()
-            .text_size(rems(1.125 * setting.ui_scale()))
+            .text_size(ui_size(1.125))
             .rounded_md()
             .border()
             .border_color(border_color)

crates/ui2/src/prelude.rs 🔗

@@ -3,9 +3,10 @@ pub use gpui3::{
     ViewContext, WindowContext,
 };
 
+use crate::settings::user_settings;
 pub use crate::{theme, ButtonVariant, ElementExt, Theme};
 
-use gpui3::{hsla, rems, rgb, AbsoluteLength, Hsla};
+use gpui3::{hsla, rems, rgb, AbsoluteLength, Hsla, Rems};
 use strum::EnumIter;
 
 #[derive(Clone, Copy)]
@@ -156,6 +157,12 @@ impl HighlightColor {
     }
 }
 
+pub fn ui_size(size: f32) -> Rems {
+    let setting = user_settings();
+
+    rems(*setting.ui_scale * size)
+}
+
 #[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, EnumIter)]
 pub enum FileSystemStatus {
     #[default]

crates/ui2/src/settings.rs 🔗

@@ -1,102 +1,70 @@
+use std::ops::Deref;
+
 use gpui3::{rems, AbsoluteLength};
 
 use crate::DisclosureControlStyle;
 
 // This is a fake static example of user settings overriding the default settings
 pub fn user_settings() -> Settings {
-    let mut settings = Settings::new();
-    settings.list_indent_depth = Some(rems(0.5).into());
+    let mut settings = Settings::default();
+    settings.list_indent_depth = SettingValue::UserDefined(rems(0.5).into());
     settings
 }
 
-#[derive(Clone, Copy)]
-pub struct TitlebarSettings {
-    pub show_project_owner: Option<bool>,
-    pub show_git_status: Option<bool>,
-    pub show_git_controls: Option<bool>,
+#[derive(Clone)]
+pub enum SettingValue<T> {
+    UserDefined(T),
+    Default(T),
 }
 
-impl Default for TitlebarSettings {
-    fn default() -> Self {
-        Self {
-            show_project_owner: Some(true),
-            show_git_status: Some(true),
-            show_git_controls: Some(true),
+impl<T> Deref for SettingValue<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        match self {
+            Self::UserDefined(value) => value,
+            Self::Default(value) => value,
         }
     }
 }
 
-#[derive(Clone, Copy)]
-pub struct Settings {
-    pub default_panel_size: Option<AbsoluteLength>,
-    pub list_disclosure_style: Option<DisclosureControlStyle>,
-    pub list_indent_depth: Option<AbsoluteLength>,
-    pub titlebar: TitlebarSettings,
-    pub ui_scale: Option<f32>,
+#[derive(Clone)]
+pub struct TitlebarSettings {
+    pub show_project_owner: SettingValue<bool>,
+    pub show_git_status: SettingValue<bool>,
+    pub show_git_controls: SettingValue<bool>,
 }
 
-// These should be merged into settings
-impl Settings {
-    pub fn new() -> Self {
+impl Default for TitlebarSettings {
+    fn default() -> Self {
         Self {
-            titlebar: TitlebarSettings::default(),
-            list_disclosure_style: None,
-            list_indent_depth: None,
-            default_panel_size: None,
-            ui_scale: None,
+            show_project_owner: SettingValue::Default(true),
+            show_git_status: SettingValue::Default(true),
+            show_git_controls: SettingValue::Default(true),
         }
     }
+}
 
-    pub fn titlebar_show_project_owner(&self) -> bool {
-        self.titlebar.show_project_owner.unwrap_or(
-            Settings::default()
-                .titlebar
-                .show_project_owner
-                .expect("titlebar_show_project_owner default not set."),
-        )
-    }
-
-    pub fn list_disclosure_style(&self) -> DisclosureControlStyle {
-        self.list_disclosure_style.unwrap_or(
-            Settings::default()
-                .list_disclosure_style
-                .expect("list_disclosure_style default not set."),
-        )
-    }
-
-    pub fn list_indent_depth(&self) -> AbsoluteLength {
-        self.list_indent_depth.unwrap_or(
-            Settings::default()
-                .list_indent_depth
-                .expect("list_indent_depth default not set."),
-        )
-    }
-
-    pub fn default_panel_size(&self) -> AbsoluteLength {
-        self.default_panel_size.unwrap_or(
-            Settings::default()
-                .default_panel_size
-                .expect("default_panel_size default not set."),
-        )
-    }
-
-    pub fn ui_scale(&self) -> f32 {
-        self.ui_scale.unwrap_or(
-            Settings::default()
-                .ui_scale
-                .expect("ui_scale default not set."),
-        )
-    }
+// These should be merged into settings
+#[derive(Clone)]
+pub struct Settings {
+    pub default_panel_size: SettingValue<AbsoluteLength>,
+    pub list_disclosure_style: SettingValue<DisclosureControlStyle>,
+    pub list_indent_depth: SettingValue<AbsoluteLength>,
+    pub titlebar: TitlebarSettings,
+    pub ui_scale: SettingValue<f32>,
 }
 
 impl Default for Settings {
     fn default() -> Self {
         Self {
             titlebar: TitlebarSettings::default(),
-            list_disclosure_style: Some(DisclosureControlStyle::ChevronOnHover),
-            list_indent_depth: Some(rems(0.3).into()),
-            default_panel_size: Some(rems(16.).into()),
-            ui_scale: Some(1.),
+            list_disclosure_style: SettingValue::Default(DisclosureControlStyle::ChevronOnHover),
+            list_indent_depth: SettingValue::Default(rems(0.3).into()),
+            default_panel_size: SettingValue::Default(rems(16.).into()),
+            ui_scale: SettingValue::Default(1.),
         }
     }
 }
+
+impl Settings {}