settings.rs

  1use std::ops::Deref;
  2use std::sync::Arc;
  3
  4use gpui3::{
  5    rems, AbsoluteLength, AnyElement, BorrowAppContext, Bounds, Interactive, LayoutId, Pixels,
  6    WindowContext,
  7};
  8
  9use crate::prelude::*;
 10
 11/// Returns the user settings.
 12pub fn user_settings(cx: &WindowContext) -> FakeSettings {
 13    cx.global::<FakeSettings>().clone()
 14}
 15
 16pub fn user_settings_mut<'cx>(cx: &'cx mut WindowContext) -> &'cx mut FakeSettings {
 17    cx.global_mut::<FakeSettings>()
 18}
 19
 20#[derive(Clone)]
 21pub enum SettingValue<T> {
 22    UserDefined(T),
 23    Default(T),
 24}
 25
 26impl<T> Deref for SettingValue<T> {
 27    type Target = T;
 28
 29    fn deref(&self) -> &Self::Target {
 30        match self {
 31            Self::UserDefined(value) => value,
 32            Self::Default(value) => value,
 33        }
 34    }
 35}
 36
 37#[derive(Clone)]
 38pub struct TitlebarSettings {
 39    pub show_project_owner: SettingValue<bool>,
 40    pub show_git_status: SettingValue<bool>,
 41    pub show_git_controls: SettingValue<bool>,
 42}
 43
 44impl Default for TitlebarSettings {
 45    fn default() -> Self {
 46        Self {
 47            show_project_owner: SettingValue::Default(true),
 48            show_git_status: SettingValue::Default(true),
 49            show_git_controls: SettingValue::Default(true),
 50        }
 51    }
 52}
 53
 54// These should be merged into settings
 55#[derive(Clone)]
 56pub struct FakeSettings {
 57    pub default_panel_size: SettingValue<AbsoluteLength>,
 58    pub list_disclosure_style: SettingValue<DisclosureControlStyle>,
 59    pub list_indent_depth: SettingValue<AbsoluteLength>,
 60    pub titlebar: TitlebarSettings,
 61    pub ui_scale: SettingValue<f32>,
 62}
 63
 64impl Default for FakeSettings {
 65    fn default() -> Self {
 66        Self {
 67            titlebar: TitlebarSettings::default(),
 68            list_disclosure_style: SettingValue::Default(DisclosureControlStyle::ChevronOnHover),
 69            list_indent_depth: SettingValue::Default(rems(0.3).into()),
 70            default_panel_size: SettingValue::Default(rems(16.).into()),
 71            ui_scale: SettingValue::Default(1.),
 72        }
 73    }
 74}
 75
 76impl FakeSettings {}
 77
 78pub fn with_settings<E, F>(
 79    settings: FakeSettings,
 80    cx: &mut ViewContext<E::ViewState>,
 81    build_child: F,
 82) -> WithSettings<E>
 83where
 84    E: Element,
 85    F: FnOnce(&mut ViewContext<E::ViewState>) -> E,
 86{
 87    let child = cx.with_global(settings.clone(), |cx| build_child(cx));
 88    WithSettings { settings, child }
 89}
 90
 91pub struct WithSettings<E> {
 92    pub(crate) settings: FakeSettings,
 93    pub(crate) child: E,
 94}
 95
 96impl<E> IntoAnyElement<E::ViewState> for WithSettings<E>
 97where
 98    E: Element,
 99{
100    fn into_any(self) -> AnyElement<E::ViewState> {
101        AnyElement::new(self)
102    }
103}
104
105impl<E: Element> Element for WithSettings<E> {
106    type ViewState = E::ViewState;
107    type ElementState = E::ElementState;
108
109    fn id(&self) -> Option<gpui3::ElementId> {
110        None
111    }
112
113    fn initialize(
114        &mut self,
115        view_state: &mut Self::ViewState,
116        element_state: Option<Self::ElementState>,
117        cx: &mut ViewContext<Self::ViewState>,
118    ) -> Self::ElementState {
119        cx.with_global(self.settings.clone(), |cx| {
120            self.child.initialize(view_state, element_state, cx)
121        })
122    }
123
124    fn layout(
125        &mut self,
126        view_state: &mut E::ViewState,
127        element_state: &mut Self::ElementState,
128        cx: &mut ViewContext<E::ViewState>,
129    ) -> LayoutId
130    where
131        Self: Sized,
132    {
133        cx.with_global(self.settings.clone(), |cx| {
134            self.child.layout(view_state, element_state, cx)
135        })
136    }
137
138    fn paint(
139        &mut self,
140        bounds: Bounds<Pixels>,
141        view_state: &mut Self::ViewState,
142        frame_state: &mut Self::ElementState,
143        cx: &mut ViewContext<Self::ViewState>,
144    ) where
145        Self: Sized,
146    {
147        cx.with_global(self.settings.clone(), |cx| {
148            self.child.paint(bounds, view_state, frame_state, cx);
149        });
150    }
151}
152
153impl<E: Element + Interactive> Interactive for WithSettings<E> {
154    fn listeners(&mut self) -> &mut gpui3::EventListeners<Self::ViewState> {
155        self.child.listeners()
156    }
157
158    fn on_mouse_down(
159        mut self,
160        button: gpui3::MouseButton,
161        handler: impl Fn(&mut Self::ViewState, &gpui3::MouseDownEvent, &mut ViewContext<Self::ViewState>)
162            + Send
163            + Sync
164            + 'static,
165    ) -> Self
166    where
167        Self: Sized,
168    {
169        println!("WithSettings on_mouse_down");
170
171        let settings = self.settings.clone();
172
173        self.listeners()
174            .mouse_down
175            .push(Arc::new(move |view, event, bounds, phase, cx| {
176                cx.with_global(settings.clone(), |cx| handler(view, event, cx))
177            }));
178        self
179    }
180}