Checkpoint

Antonio Scandurra created

Change summary

crates/gpui3/src/element.rs      | 156 +++++++++++---
crates/gpui3/src/elements/div.rs |  98 +--------
crates/ui2/src/prelude.rs        |   4 
crates/ui2/src/settings.rs       | 359 ++++++++++++++++-----------------
4 files changed, 314 insertions(+), 303 deletions(-)

Detailed changes

crates/gpui3/src/element.rs 🔗

@@ -1,10 +1,11 @@
 use crate::{
-    BorrowWindow, Bounds, DispatchPhase, ElementId, FocusHandle, FocusListeners, KeyDownEvent,
-    KeyListener, KeyMatch, LayoutId, MouseClickEvent, MouseClickListener, MouseDownEvent,
-    MouseDownListener, MouseMoveEvent, MouseMoveListener, MouseUpEvent, MouseUpListener, Pixels,
-    Point, ScrollWheelEvent, ScrollWheelListener, Style, StyleRefinement, ViewContext,
-    WindowContext,
+    AppContext, BorrowWindow, Bounds, DispatchPhase, ElementId, FocusHandle, FocusListeners,
+    KeyDownEvent, KeyListener, KeyMatch, LayoutId, MouseClickEvent, MouseClickListener,
+    MouseDownEvent, MouseDownListener, MouseMoveEvent, MouseMoveListener, MouseUpEvent,
+    MouseUpListener, Pixels, Point, ScrollWheelEvent, ScrollWheelListener, SharedString, Style,
+    StyleRefinement, ViewContext, WindowContext,
 };
+use collections::HashMap;
 use derive_more::{Deref, DerefMut};
 use parking_lot::Mutex;
 use refineable::Refineable;
@@ -49,6 +50,52 @@ pub trait ElementInteractivity<V: 'static + Send + Sync>: 'static + Send + Sync
     fn as_stateful(&self) -> Option<&StatefulInteractivity<V>>;
     fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity<V>>;
 
+    fn initialize<R>(
+        &mut self,
+        cx: &mut ViewContext<V>,
+        f: impl FnOnce(&mut ViewContext<V>) -> R,
+    ) -> R {
+        if let Some(stateful) = self.as_stateful_mut() {
+            cx.with_element_id(stateful.id.clone(), |global_id, cx| {
+                stateful.key_listeners.push((
+                    TypeId::of::<KeyDownEvent>(),
+                    Arc::new(move |_, key_down, context, phase, cx| {
+                        if phase == DispatchPhase::Bubble {
+                            let key_down = key_down.downcast_ref::<KeyDownEvent>().unwrap();
+                            if let KeyMatch::Some(action) =
+                                cx.match_keystroke(&global_id, &key_down.keystroke, context)
+                            {
+                                return Some(action);
+                            }
+                        }
+
+                        None
+                    }),
+                ));
+                let result = stateful.stateless.initialize(cx, f);
+                stateful.key_listeners.pop();
+                result
+            })
+        } else {
+            cx.with_key_listeners(&self.as_stateless().key_listeners, f)
+        }
+    }
+
+    fn refine_style(&self, style: &mut Style, bounds: Bounds<Pixels>, cx: &mut ViewContext<V>) {
+        let mouse_position = cx.mouse_position();
+        let stateless = self.as_stateless();
+        if let Some(group_hover) = stateless.group_hover.as_ref() {
+            if let Some(group_bounds) = group_bounds(&group_hover.group, cx) {
+                if group_bounds.contains_point(&mouse_position) {
+                    style.refine(&group_hover.style);
+                }
+            }
+        }
+        if bounds.contains_point(&mouse_position) {
+            style.refine(&stateless.hover_style);
+        }
+    }
+
     fn paint(
         &mut self,
         bounds: Bounds<Pixels>,
@@ -80,6 +127,19 @@ pub trait ElementInteractivity<V: 'static + Send + Sync>: 'static + Send + Sync
             })
         }
 
+        let hover_group_bounds = stateless
+            .group_hover
+            .as_ref()
+            .and_then(|group_hover| GroupBounds::get(&group_hover.group, cx));
+
+        if let Some(group_bounds) = hover_group_bounds {
+            paint_hover_listener(group_bounds, cx);
+        }
+
+        if stateless.hover_style.is_some() {
+            paint_hover_listener(bounds, cx);
+        }
+
         if let Some(stateful) = self.as_stateful() {
             let click_listeners = stateful.mouse_click_listeners.clone();
 
@@ -107,37 +167,20 @@ pub trait ElementInteractivity<V: 'static + Send + Sync>: 'static + Send + Sync
             };
         }
     }
+}
 
-    fn initialize<R>(
-        &mut self,
-        cx: &mut ViewContext<V>,
-        f: impl FnOnce(&mut ViewContext<V>) -> R,
-    ) -> R {
-        if let Some(stateful) = self.as_stateful_mut() {
-            cx.with_element_id(stateful.id.clone(), |global_id, cx| {
-                stateful.key_listeners.push((
-                    TypeId::of::<KeyDownEvent>(),
-                    Arc::new(move |_, key_down, context, phase, cx| {
-                        if phase == DispatchPhase::Bubble {
-                            let key_down = key_down.downcast_ref::<KeyDownEvent>().unwrap();
-                            if let KeyMatch::Some(action) =
-                                cx.match_keystroke(&global_id, &key_down.keystroke, context)
-                            {
-                                return Some(action);
-                            }
-                        }
-
-                        None
-                    }),
-                ));
-                let result = stateful.stateless.initialize(cx, f);
-                stateful.key_listeners.pop();
-                result
-            })
-        } else {
-            cx.with_key_listeners(&self.as_stateless().key_listeners, f)
+fn paint_hover_listener<V>(bounds: Bounds<Pixels>, cx: &mut ViewContext<V>)
+where
+    V: 'static + Send + Sync,
+{
+    let hovered = bounds.contains_point(&cx.mouse_position());
+    cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| {
+        if phase == DispatchPhase::Capture {
+            if bounds.contains_point(&event.position) != hovered {
+                cx.notify();
+            }
         }
-    }
+    });
 }
 
 #[derive(Deref, DerefMut)]
@@ -189,6 +232,49 @@ pub struct StatelessInteractivity<V> {
     pub mouse_move_listeners: SmallVec<[MouseMoveListener<V>; 2]>,
     pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener<V>; 2]>,
     pub key_listeners: SmallVec<[(TypeId, KeyListener<V>); 32]>,
+    pub hover_style: StyleRefinement,
+    pub group_hover: Option<GroupStyle>,
+}
+
+pub struct GroupStyle {
+    pub group: SharedString,
+    pub style: StyleRefinement,
+}
+
+#[derive(Default)]
+pub struct GroupBounds(HashMap<SharedString, SmallVec<[Bounds<Pixels>; 1]>>);
+
+impl GroupBounds {
+    pub fn get(name: &SharedString, cx: &mut AppContext) -> Option<Bounds<Pixels>> {
+        cx.default_global::<Self>()
+            .0
+            .get(name)
+            .and_then(|bounds_stack| bounds_stack.last())
+            .cloned()
+    }
+
+    pub fn push(name: SharedString, bounds: Bounds<Pixels>, cx: &mut AppContext) {
+        cx.default_global::<Self>()
+            .0
+            .entry(name)
+            .or_default()
+            .push(bounds);
+    }
+
+    pub fn pop(name: &SharedString, cx: &mut AppContext) {
+        cx.default_global::<GroupBounds>()
+            .0
+            .get_mut(name)
+            .unwrap()
+            .pop();
+    }
+}
+
+pub fn group_bounds(name: &SharedString, cx: &mut AppContext) -> Option<Bounds<Pixels>> {
+    cx.default_global::<GroupBounds>()
+        .0
+        .get(name)
+        .and_then(|bounds_stack| bounds_stack.last().cloned())
 }
 
 impl<V> Default for StatelessInteractivity<V> {
@@ -199,6 +285,8 @@ impl<V> Default for StatelessInteractivity<V> {
             mouse_move_listeners: SmallVec::new(),
             scroll_wheel_listeners: SmallVec::new(),
             key_listeners: SmallVec::new(),
+            hover_style: StyleRefinement::default(),
+            group_hover: None,
         }
     }
 }

crates/gpui3/src/elements/div.rs 🔗

@@ -1,12 +1,11 @@
 use crate::{
-    Active, AnyElement, AppContext, BorrowWindow, Bounds, DispatchPhase, Element,
-    ElementFocusability, ElementId, ElementInteractivity, Focus, FocusHandle, FocusListeners,
-    Focusable, GlobalElementId, Hover, IntoAnyElement, LayoutId, MouseDownEvent, MouseMoveEvent,
+    Active, AnyElement, BorrowWindow, Bounds, DispatchPhase, Element, ElementFocusability,
+    ElementId, ElementInteractivity, Focus, FocusHandle, FocusListeners, Focusable,
+    GlobalElementId, GroupBounds, GroupStyle, Hover, IntoAnyElement, LayoutId, MouseDownEvent,
     MouseUpEvent, NonFocusable, Overflow, ParentElement, Pixels, Point, SharedString,
     StatefulInteractivity, StatefullyInteractive, StatelessInteractivity, StatelesslyInteractive,
     Style, StyleRefinement, Styled, ViewContext,
 };
-use collections::HashMap;
 use parking_lot::Mutex;
 use refineable::Refineable;
 use smallvec::SmallVec;
@@ -30,16 +29,6 @@ impl ActiveState {
     }
 }
 
-#[derive(Default)]
-struct GroupBounds(HashMap<SharedString, SmallVec<[Bounds<Pixels>; 1]>>);
-
-pub fn group_bounds(name: &SharedString, cx: &mut AppContext) -> Option<Bounds<Pixels>> {
-    cx.default_global::<GroupBounds>()
-        .0
-        .get(name)
-        .and_then(|bounds_stack| bounds_stack.last().cloned())
-}
-
 #[derive(Default, Clone)]
 pub struct ScrollState(Arc<Mutex<Point<Pixels>>>);
 
@@ -71,8 +60,6 @@ pub struct Div<
     children: SmallVec<[AnyElement<V>; 2]>,
     group: Option<SharedString>,
     base_style: StyleRefinement,
-    hover_style: StyleRefinement,
-    group_hover: Option<GroupStyle>,
     active_style: StyleRefinement,
     group_active: Option<GroupStyle>,
 }
@@ -87,18 +74,11 @@ where
         children: SmallVec::new(),
         group: None,
         base_style: StyleRefinement::default(),
-        hover_style: StyleRefinement::default(),
-        group_hover: None,
         active_style: StyleRefinement::default(),
         group_active: None,
     }
 }
 
-struct GroupStyle {
-    group: SharedString,
-    style: StyleRefinement,
-}
-
 impl<V, F> Div<V, StatelessInteractivity<V>, F>
 where
     F: ElementFocusability<V>,
@@ -111,8 +91,6 @@ where
             children: self.children,
             group: self.group,
             base_style: self.base_style,
-            hover_style: self.hover_style,
-            group_hover: self.group_hover,
             active_style: self.active_style,
             group_active: self.group_active,
         }
@@ -195,19 +173,8 @@ where
         computed_style.refine(&self.base_style);
 
         self.focusability.refine_style(&mut computed_style, cx);
-
-        let mouse_position = cx.mouse_position();
-
-        if let Some(group_hover) = self.group_hover.as_ref() {
-            if let Some(group_bounds) = group_bounds(&group_hover.group, cx) {
-                if group_bounds.contains_point(&mouse_position) {
-                    computed_style.refine(&group_hover.style);
-                }
-            }
-        }
-        if bounds.contains_point(&mouse_position) {
-            computed_style.refine(&self.hover_style);
-        }
+        self.interactivity
+            .refine_style(&mut computed_style, bounds, cx);
 
         let active_state = *state.active_state.lock();
         if active_state.group {
@@ -222,21 +189,6 @@ where
         computed_style
     }
 
-    fn paint_hover_listeners(
-        &self,
-        bounds: Bounds<Pixels>,
-        group_bounds: Option<Bounds<Pixels>>,
-        cx: &mut ViewContext<V>,
-    ) {
-        if let Some(group_bounds) = group_bounds {
-            paint_hover_listener(group_bounds, cx);
-        }
-
-        if self.hover_style.is_some() {
-            paint_hover_listener(bounds, cx);
-        }
-    }
-
     fn paint_active_listener(
         &self,
         bounds: Bounds<Pixels>,
@@ -279,8 +231,6 @@ where
             children: self.children,
             group: self.group,
             base_style: self.base_style,
-            hover_style: self.hover_style,
-            group_hover: self.group_hover,
             active_style: self.active_style,
             group_active: self.group_active,
         }
@@ -372,21 +322,13 @@ where
     ) {
         self.with_element_id(cx, |this, _global_id, cx| {
             if let Some(group) = this.group.clone() {
-                cx.default_global::<GroupBounds>()
-                    .0
-                    .entry(group)
-                    .or_default()
-                    .push(bounds);
+                GroupBounds::push(group, bounds, cx);
             }
 
-            let hover_group_bounds = this
-                .group_hover
-                .as_ref()
-                .and_then(|group_hover| group_bounds(&group_hover.group, cx));
             let active_group_bounds = this
                 .group_active
                 .as_ref()
-                .and_then(|group_active| group_bounds(&group_active.group, cx));
+                .and_then(|group_active| GroupBounds::get(&group_active.group, cx));
             let style = this.compute_style(bounds, element_state, cx);
             let z_index = style.z_index.unwrap_or(0);
 
@@ -394,7 +336,6 @@ where
             cx.stack(z_index, |cx| {
                 cx.stack(0, |cx| {
                     style.paint(bounds, cx);
-                    this.paint_hover_listeners(bounds, hover_group_bounds, cx);
                     this.paint_active_listener(
                         bounds,
                         active_group_bounds,
@@ -418,11 +359,7 @@ where
             });
 
             if let Some(group) = this.group.as_ref() {
-                cx.default_global::<GroupBounds>()
-                    .0
-                    .get_mut(group)
-                    .unwrap()
-                    .pop();
+                GroupBounds::pop(group, cx);
             }
         })
     }
@@ -479,10 +416,11 @@ where
     V: 'static + Send + Sync,
 {
     fn set_hover_style(&mut self, group: Option<SharedString>, style: StyleRefinement) {
+        let stateless = self.interactivity.as_stateless_mut();
         if let Some(group) = group {
-            self.group_hover = Some(GroupStyle { group, style });
+            stateless.group_hover = Some(GroupStyle { group, style });
         } else {
-            self.hover_style = style;
+            stateless.hover_style = style;
         }
     }
 }
@@ -510,17 +448,3 @@ where
         }
     }
 }
-
-fn paint_hover_listener<V>(bounds: Bounds<Pixels>, cx: &mut ViewContext<V>)
-where
-    V: 'static + Send + Sync,
-{
-    let hovered = bounds.contains_point(&cx.mouse_position());
-    cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| {
-        if phase == DispatchPhase::Capture {
-            if bounds.contains_point(&event.position) != hovered {
-                cx.notify();
-            }
-        }
-    });
-}

crates/ui2/src/prelude.rs 🔗

@@ -1,6 +1,6 @@
 pub use gpui3::{
-    div, Click, Element, Hover, IntoAnyElement, ParentElement, ScrollState, SharedString,
-    StatefullyInteractivee, Styled, ViewContext, WindowContext,
+    div, Element, Hover, IntoAnyElement, ParentElement, ScrollState, SharedString,
+    StatefullyInteractive, Styled, ViewContext, WindowContext,
 };
 
 use crate::settings::user_settings;

crates/ui2/src/settings.rs 🔗

@@ -1,180 +1,179 @@
-use std::ops::Deref;
-use std::sync::Arc;
-
-use gpui3::{
-    rems, AbsoluteLength, AnyElement, BorrowAppContext, Bounds, Interactive, LayoutId, Pixels,
-    WindowContext,
-};
-
-use crate::prelude::*;
-
-/// Returns the user settings.
-pub fn user_settings(cx: &WindowContext) -> FakeSettings {
-    cx.global::<FakeSettings>().clone()
-}
-
-pub fn user_settings_mut<'cx>(cx: &'cx mut WindowContext) -> &'cx mut FakeSettings {
-    cx.global_mut::<FakeSettings>()
-}
-
-#[derive(Clone)]
-pub enum SettingValue<T> {
-    UserDefined(T),
-    Default(T),
-}
-
-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)]
-pub struct TitlebarSettings {
-    pub show_project_owner: SettingValue<bool>,
-    pub show_git_status: SettingValue<bool>,
-    pub show_git_controls: SettingValue<bool>,
-}
-
-impl Default for TitlebarSettings {
-    fn default() -> Self {
-        Self {
-            show_project_owner: SettingValue::Default(true),
-            show_git_status: SettingValue::Default(true),
-            show_git_controls: SettingValue::Default(true),
-        }
-    }
-}
-
-// These should be merged into settings
-#[derive(Clone)]
-pub struct FakeSettings {
-    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 FakeSettings {
-    fn default() -> Self {
-        Self {
-            titlebar: TitlebarSettings::default(),
-            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 FakeSettings {}
-
-pub fn with_settings<E, F>(
-    settings: FakeSettings,
-    cx: &mut ViewContext<E::ViewState>,
-    build_child: F,
-) -> WithSettings<E>
-where
-    E: Element,
-    F: FnOnce(&mut ViewContext<E::ViewState>) -> E,
-{
-    let child = cx.with_global(settings.clone(), |cx| build_child(cx));
-    WithSettings { settings, child }
-}
-
-pub struct WithSettings<E> {
-    pub(crate) settings: FakeSettings,
-    pub(crate) child: E,
-}
-
-impl<E> IntoAnyElement<E::ViewState> for WithSettings<E>
-where
-    E: Element,
-{
-    fn into_any(self) -> AnyElement<E::ViewState> {
-        AnyElement::new(self)
-    }
-}
-
-impl<E: Element> Element for WithSettings<E> {
-    type ViewState = E::ViewState;
-    type ElementState = E::ElementState;
-
-    fn id(&self) -> Option<gpui3::ElementId> {
-        None
-    }
-
-    fn initialize(
-        &mut self,
-        view_state: &mut Self::ViewState,
-        element_state: Option<Self::ElementState>,
-        cx: &mut ViewContext<Self::ViewState>,
-    ) -> Self::ElementState {
-        cx.with_global(self.settings.clone(), |cx| {
-            self.child.initialize(view_state, element_state, cx)
-        })
-    }
-
-    fn layout(
-        &mut self,
-        view_state: &mut E::ViewState,
-        element_state: &mut Self::ElementState,
-        cx: &mut ViewContext<E::ViewState>,
-    ) -> LayoutId
-    where
-        Self: Sized,
-    {
-        cx.with_global(self.settings.clone(), |cx| {
-            self.child.layout(view_state, element_state, cx)
-        })
-    }
-
-    fn paint(
-        &mut self,
-        bounds: Bounds<Pixels>,
-        view_state: &mut Self::ViewState,
-        frame_state: &mut Self::ElementState,
-        cx: &mut ViewContext<Self::ViewState>,
-    ) where
-        Self: Sized,
-    {
-        cx.with_global(self.settings.clone(), |cx| {
-            self.child.paint(bounds, view_state, frame_state, cx);
-        });
-    }
-}
-
-impl<E: Element + Interactive> Interactive for WithSettings<E> {
-    fn listeners(&mut self) -> &mut gpui3::EventListeners<Self::ViewState> {
-        self.child.listeners()
-    }
-
-    fn on_mouse_down(
-        mut self,
-        button: gpui3::MouseButton,
-        handler: impl Fn(&mut Self::ViewState, &gpui3::MouseDownEvent, &mut ViewContext<Self::ViewState>)
-            + Send
-            + Sync
-            + 'static,
-    ) -> Self
-    where
-        Self: Sized,
-    {
-        println!("WithSettings on_mouse_down");
-
-        let settings = self.settings.clone();
-
-        self.listeners()
-            .mouse_down
-            .push(Arc::new(move |view, event, bounds, phase, cx| {
-                cx.with_global(settings.clone(), |cx| handler(view, event, cx))
-            }));
-        self
-    }
-}
+// use std::ops::Deref;
+// use std::sync::Arc;
+
+// use gpui3::{
+//     rems, AbsoluteLength, AnyElement, BorrowAppContext, Bounds, LayoutId, Pixels, WindowContext,
+// };
+
+// use crate::prelude::*;
+
+// /// Returns the user settings.
+// pub fn user_settings(cx: &WindowContext) -> FakeSettings {
+//     cx.global::<FakeSettings>().clone()
+// }
+
+// pub fn user_settings_mut<'cx>(cx: &'cx mut WindowContext) -> &'cx mut FakeSettings {
+//     cx.global_mut::<FakeSettings>()
+// }
+
+// #[derive(Clone)]
+// pub enum SettingValue<T> {
+//     UserDefined(T),
+//     Default(T),
+// }
+
+// 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)]
+// pub struct TitlebarSettings {
+//     pub show_project_owner: SettingValue<bool>,
+//     pub show_git_status: SettingValue<bool>,
+//     pub show_git_controls: SettingValue<bool>,
+// }
+
+// impl Default for TitlebarSettings {
+//     fn default() -> Self {
+//         Self {
+//             show_project_owner: SettingValue::Default(true),
+//             show_git_status: SettingValue::Default(true),
+//             show_git_controls: SettingValue::Default(true),
+//         }
+//     }
+// }
+
+// // These should be merged into settings
+// #[derive(Clone)]
+// pub struct FakeSettings {
+//     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 FakeSettings {
+//     fn default() -> Self {
+//         Self {
+//             titlebar: TitlebarSettings::default(),
+//             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 FakeSettings {}
+
+// pub fn with_settings<E, F>(
+//     settings: FakeSettings,
+//     cx: &mut ViewContext<E::ViewState>,
+//     build_child: F,
+// ) -> WithSettings<E>
+// where
+//     E: Element,
+//     F: FnOnce(&mut ViewContext<E::ViewState>) -> E,
+// {
+//     let child = cx.with_global(settings.clone(), |cx| build_child(cx));
+//     WithSettings { settings, child }
+// }
+
+// pub struct WithSettings<E> {
+//     pub(crate) settings: FakeSettings,
+//     pub(crate) child: E,
+// }
+
+// impl<E> IntoAnyElement<E::ViewState> for WithSettings<E>
+// where
+//     E: Element,
+// {
+//     fn into_any(self) -> AnyElement<E::ViewState> {
+//         AnyElement::new(self)
+//     }
+// }
+
+// impl<E: Element> Element for WithSettings<E> {
+//     type ViewState = E::ViewState;
+//     type ElementState = E::ElementState;
+
+//     fn id(&self) -> Option<gpui3::ElementId> {
+//         None
+//     }
+
+//     fn initialize(
+//         &mut self,
+//         view_state: &mut Self::ViewState,
+//         element_state: Option<Self::ElementState>,
+//         cx: &mut ViewContext<Self::ViewState>,
+//     ) -> Self::ElementState {
+//         cx.with_global(self.settings.clone(), |cx| {
+//             self.child.initialize(view_state, element_state, cx)
+//         })
+//     }
+
+//     fn layout(
+//         &mut self,
+//         view_state: &mut E::ViewState,
+//         element_state: &mut Self::ElementState,
+//         cx: &mut ViewContext<E::ViewState>,
+//     ) -> LayoutId
+//     where
+//         Self: Sized,
+//     {
+//         cx.with_global(self.settings.clone(), |cx| {
+//             self.child.layout(view_state, element_state, cx)
+//         })
+//     }
+
+//     fn paint(
+//         &mut self,
+//         bounds: Bounds<Pixels>,
+//         view_state: &mut Self::ViewState,
+//         frame_state: &mut Self::ElementState,
+//         cx: &mut ViewContext<Self::ViewState>,
+//     ) where
+//         Self: Sized,
+//     {
+//         cx.with_global(self.settings.clone(), |cx| {
+//             self.child.paint(bounds, view_state, frame_state, cx);
+//         });
+//     }
+// }
+
+// impl<E: Element + Interactive> Interactive for WithSettings<E> {
+//     fn listeners(&mut self) -> &mut gpui3::EventListeners<Self::ViewState> {
+//         self.child.listeners()
+//     }
+
+//     fn on_mouse_down(
+//         mut self,
+//         button: gpui3::MouseButton,
+//         handler: impl Fn(&mut Self::ViewState, &gpui3::MouseDownEvent, &mut ViewContext<Self::ViewState>)
+//             + Send
+//             + Sync
+//             + 'static,
+//     ) -> Self
+//     where
+//         Self: Sized,
+//     {
+//         println!("WithSettings on_mouse_down");
+
+//         let settings = self.settings.clone();
+
+//         self.listeners()
+//             .mouse_down
+//             .push(Arc::new(move |view, event, bounds, phase, cx| {
+//                 cx.with_global(settings.clone(), |cx| handler(view, event, cx))
+//             }));
+//         self
+//     }
+// }