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}