Checkpoint

Antonio Scandurra created

Change summary

crates/gpui3/src/element.rs             |  9 +++++++
crates/gpui3/src/elements/hoverable.rs  | 10 +++++++-
crates/gpui3/src/elements/identified.rs | 26 +++++++++++++++---------
crates/gpui3/src/gpui3.rs               | 21 +++++++++++++------
crates/gpui3/src/identified.rs          |  1 
crates/gpui3/src/window.rs              | 28 +++++++++++++++++++-------
6 files changed, 67 insertions(+), 28 deletions(-)

Detailed changes

crates/gpui3/src/element.rs 🔗

@@ -1,4 +1,4 @@
-use crate::Bounds;
+use crate::{Bounds, ElementId, ElementWithId};
 
 use super::{LayoutId, Pixels, Point, Result, ViewContext};
 pub(crate) use smallvec::SmallVec;
@@ -20,6 +20,13 @@ pub trait Element: 'static {
         frame_state: &mut Self::FrameState,
         cx: &mut ViewContext<Self::State>,
     ) -> Result<()>;
+
+    fn id(self, id: ElementId) -> ElementWithId<Self>
+    where
+        Self: Sized,
+    {
+        ElementWithId { element: self, id }
+    }
 }
 
 pub trait ParentElement {

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

@@ -1,6 +1,6 @@
 use crate::{
-    AnyElement, Bounds, DispatchPhase, Element, Interactive, MouseEventListeners, MouseMoveEvent,
-    ParentElement, Pixels, Styled, ViewContext,
+    AnyElement, Bounds, DispatchPhase, Element, ElementId, Identified, Interactive,
+    MouseEventListeners, MouseMoveEvent, ParentElement, Pixels, Styled, ViewContext,
 };
 use anyhow::Result;
 use refineable::{CascadeSlot, Refineable, RefinementCascade};
@@ -95,3 +95,9 @@ impl<E: ParentElement + Styled> ParentElement for Hoverable<E> {
         self.child.children_mut()
     }
 }
+
+impl<E: Identified + Styled> Identified for Hoverable<E> {
+    fn id(&self) -> ElementId {
+        self.child.id()
+    }
+}

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

@@ -1,16 +1,16 @@
-use crate::{ElementId, Element, Bounds, ViewContext, LayoutId};
+use crate::{BorrowWindow, Bounds, Element, ElementId, LayoutId, ViewContext};
 use anyhow::Result;
-use derive_more::{Deref, DerefMut}
 
-#[derive(Deref, DerefMut)]
-pub struct Identified<E> {
-    #[deref]
-    #[deref_mut]
-    element: E,
-    id: ElementId,
+pub trait Identified {
+    fn id(&self) -> ElementId;
 }
 
-impl<E: Element> Element for Identified<E> {
+pub struct ElementWithId<E> {
+    pub(crate) element: E,
+    pub(crate) id: ElementId,
+}
+
+impl<E: Element> Element for ElementWithId<E> {
     type State = E::State;
     type FrameState = E::FrameState;
 
@@ -29,8 +29,14 @@ impl<E: Element> Element for Identified<E> {
         frame_state: &mut Self::FrameState,
         cx: &mut ViewContext<Self::State>,
     ) -> Result<()> {
-        cx.with_element_id(self.id, |cx| {
+        cx.with_element_id(self.id.clone(), |cx| {
             self.element.paint(bounds, state, frame_state, cx)
         })
     }
 }
+
+impl<E> Identified for ElementWithId<E> {
+    fn id(&self) -> ElementId {
+        self.id.clone()
+    }
+}

crates/gpui3/src/gpui3.rs 🔗

@@ -6,6 +6,7 @@ mod elements;
 mod events;
 mod executor;
 mod geometry;
+mod identified;
 mod image_cache;
 mod interactive;
 mod platform;
@@ -30,6 +31,7 @@ pub use events::*;
 pub use executor::*;
 pub use geometry::*;
 pub use gpui3_macros::*;
+pub use identified::*;
 pub use image_cache::*;
 pub use interactive::*;
 pub use platform::*;
@@ -39,22 +41,24 @@ pub use serde;
 pub use serde_json;
 pub use smallvec;
 pub use smol::Timer;
-use std::{
-    mem,
-    ops::{Deref, DerefMut},
-    sync::Arc,
-};
 pub use style::*;
 pub use style_helpers::*;
 pub use styled::*;
 pub use svg_renderer::*;
-use taffy::TaffyLayoutEngine;
 pub use taffy::{AvailableSpace, LayoutId};
 pub use text_system::*;
 pub use util::arc_cow::ArcCow;
 pub use view::*;
 pub use window::*;
 
+use derive_more::{Deref, DerefMut};
+use std::{
+    mem,
+    ops::{Deref, DerefMut},
+    sync::Arc,
+};
+use taffy::TaffyLayoutEngine;
+
 pub trait Context {
     type EntityContext<'a, 'w, T: 'static + Send + Sync>;
     type Result<T>;
@@ -167,9 +171,12 @@ impl<T> Flatten<T> for Result<T> {
 #[derive(Clone, Eq, PartialEq, Hash)]
 pub struct SharedString(ArcCow<'static, str>);
 
-#[derive(Clone, Eq, PartialEq, Hash)]
+#[derive(Clone, Debug, Eq, PartialEq, Hash)]
 pub struct ElementId(ArcCow<'static, [u8]>);
 
+#[derive(Default, Deref, DerefMut, Clone, Debug)]
+pub(crate) struct GlobalElementId(SmallVec<[ElementId; 8]>);
+
 impl Default for SharedString {
     fn default() -> Self {
         Self(ArcCow::Owned("".into()))

crates/gpui3/src/window.rs 🔗

@@ -1,12 +1,12 @@
 use crate::{
     image_cache::RenderImageParams, px, size, AnyView, AppContext, AsyncWindowContext,
     AvailableSpace, BorrowAppContext, Bounds, BoxShadow, Context, Corners, DevicePixels, DisplayId,
-    Edges, Effect, Element, ElementId, EntityId, Event, FontId, GlyphId, Handle, Hsla, ImageData,
-    IsZero, LayoutId, MainThread, MainThreadOnly, MonochromeSprite, MouseMoveEvent, Path, Pixels,
-    PlatformAtlas, PlatformWindow, Point, PolychromeSprite, Quad, Reference, RenderGlyphParams,
-    RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size, Style,
-    TaffyLayoutEngine, Task, Underline, UnderlineStyle, WeakHandle, WindowOptions,
-    SUBPIXEL_VARIANTS,
+    Edges, Effect, Element, ElementId, EntityId, Event, FontId, GlobalElementId, GlyphId, Handle,
+    Hsla, ImageData, IsZero, LayoutId, MainThread, MainThreadOnly, MonochromeSprite,
+    MouseMoveEvent, Path, Pixels, PlatformAtlas, PlatformWindow, Point, PolychromeSprite, Quad,
+    Reference, RenderGlyphParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow,
+    SharedString, Size, Style, TaffyLayoutEngine, Task, Underline, UnderlineStyle, WeakHandle,
+    WindowOptions, SUBPIXEL_VARIANTS,
 };
 use anyhow::Result;
 use collections::HashMap;
@@ -21,7 +21,7 @@ use std::{
     mem,
     sync::Arc,
 };
-use util::{arc_cow::ArcCow, ResultExt};
+use util::ResultExt;
 
 #[derive(Deref, DerefMut, Ord, PartialOrd, Eq, PartialEq, Clone, Default)]
 pub struct StackingOrder(pub(crate) SmallVec<[u32; 16]>);
@@ -51,7 +51,7 @@ pub struct Window {
     content_size: Size<Pixels>,
     layout_engine: TaffyLayoutEngine,
     pub(crate) root_view: Option<AnyView<()>>,
-    element_id_stack: SmallVec<[ElementId; 8]>,
+    pub(crate) element_id_stack: GlobalElementId,
     z_index_stack: StackingOrder,
     content_mask_stack: Vec<ContentMask<Pixels>>,
     mouse_event_handlers: HashMap<TypeId, Vec<(StackingOrder, MouseEventHandler)>>,
@@ -113,6 +113,7 @@ impl Window {
             content_size,
             layout_engine: TaffyLayoutEngine::new(),
             root_view: None,
+            element_id_stack: GlobalElementId::default(),
             z_index_stack: StackingOrder(SmallVec::new()),
             content_mask_stack: Vec::new(),
             mouse_event_handlers: HashMap::default(),
@@ -729,6 +730,17 @@ pub trait BorrowWindow: BorrowAppContext {
     fn window(&self) -> &Window;
     fn window_mut(&mut self) -> &mut Window;
 
+    fn with_element_id<R>(
+        &mut self,
+        id: impl Into<ElementId>,
+        f: impl FnOnce(&mut Self) -> R,
+    ) -> R {
+        self.window_mut().element_id_stack.push(id.into());
+        let result = f(self);
+        self.window_mut().element_id_stack.pop();
+        result
+    }
+
     fn with_content_mask<R>(
         &mut self,
         mask: ContentMask<Pixels>,