diff --git a/crates/gpui3/src/element.rs b/crates/gpui3/src/element.rs index 60d8d5d507..dd8b3cb3b1 100644 --- a/crates/gpui3/src/element.rs +++ b/crates/gpui3/src/element.rs @@ -25,11 +25,14 @@ pub trait Element: 'static + Send + Sync { cx: &mut ViewContext, ); - fn id(self, id: ElementId) -> Identified + fn id(self, id: impl Into) -> Identified where Self: Sized, { - Identified { element: self, id } + Identified { + element: self, + id: id.into(), + } } } diff --git a/crates/gpui3/src/elements/identified.rs b/crates/gpui3/src/elements/identified.rs index 8504778dfb..66249137a2 100644 --- a/crates/gpui3/src/elements/identified.rs +++ b/crates/gpui3/src/elements/identified.rs @@ -1,4 +1,10 @@ -use crate::{BorrowWindow, Bounds, Element, ElementId, LayoutId, StatefulElement, ViewContext}; +use refineable::{Refineable, RefinementCascade}; +use smallvec::SmallVec; + +use crate::{ + AnyElement, BorrowWindow, Bounds, Element, ElementId, LayoutId, ParentElement, StatefulElement, + Styled, ViewContext, +}; pub struct Identified { pub(crate) element: E, @@ -36,3 +42,22 @@ impl Element for Identified { } impl StatefulElement for Identified {} + +impl Styled for Identified { + type Style = E::Style; + + fn style_cascade(&mut self) -> &mut RefinementCascade { + self.element.style_cascade() + } + fn declared_style(&mut self) -> &mut ::Refinement { + self.element.declared_style() + } +} + +impl ParentElement for Identified { + type State = E::State; + + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { + self.element.children_mut() + } +} diff --git a/crates/gpui3/src/elements/pressable.rs b/crates/gpui3/src/elements/pressable.rs index e3f43e5ea7..67e1fe9ea5 100644 --- a/crates/gpui3/src/elements/pressable.rs +++ b/crates/gpui3/src/elements/pressable.rs @@ -92,25 +92,29 @@ where element_state: &mut Self::ElementState, cx: &mut ViewContext, ) { - let slot = self.cascade_slot; let style = element_state .pressed .load(SeqCst) .then_some(self.pressed_style.clone()); + let slot = self.cascade_slot; self.style_cascade().set(slot, style); let pressed = element_state.pressed.clone(); cx.on_mouse_event(move |_, event: &MouseDownEvent, phase, cx| { if phase == DispatchPhase::Capture { - if bounds.contains_point(event.position) != pressed.load(SeqCst) { + if bounds.contains_point(event.position) { + dbg!("pressed"); + pressed.store(true, SeqCst); cx.notify(); } } }); - let hovered = element_state.pressed.clone(); - cx.on_mouse_event(move |_, event: &MouseUpEvent, phase, cx| { + let pressed = element_state.pressed.clone(); + cx.on_mouse_event(move |_, _: &MouseUpEvent, phase, cx| { if phase == DispatchPhase::Capture { - if bounds.contains_point(event.position) != hovered.load(SeqCst) { + if pressed.load(SeqCst) { + dbg!("released"); + pressed.store(false, SeqCst); cx.notify(); } } diff --git a/crates/gpui3/src/styled.rs b/crates/gpui3/src/styled.rs index 3c91668494..c14b7068f5 100644 --- a/crates/gpui3/src/styled.rs +++ b/crates/gpui3/src/styled.rs @@ -1,4 +1,4 @@ -use crate::{Hoverable, Refineable, RefinementCascade}; +use crate::{Hoverable, Pressable, Refineable, RefinementCascade}; pub trait Styled { type Style: 'static + Refineable + Send + Sync + Default; @@ -19,10 +19,12 @@ pub trait Styled { Hoverable::new(self) } - // fn active(self) -> Pressable - // where - // Self: Sized, - // { - // pressable(self) - // } + fn active(self) -> Pressable + where + Self: 'static + Sized + Send + Sync, + Self::Style: 'static + Refineable + Default + Send + Sync, + ::Refinement: 'static + Default + Send + Sync, + { + Pressable::new(self) + } } diff --git a/crates/gpui3/src/window.rs b/crates/gpui3/src/window.rs index c605865b7c..bf68cd679f 100644 --- a/crates/gpui3/src/window.rs +++ b/crates/gpui3/src/window.rs @@ -1061,3 +1061,21 @@ impl From> for StackingOrder { #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct ElementId(ArcCow<'static, [u8]>); + +impl From for ElementId { + fn from(id: usize) -> Self { + Self(id.to_ne_bytes().to_vec().into()) + } +} + +impl From for ElementId { + fn from(id: i32) -> Self { + Self(id.to_ne_bytes().to_vec().into()) + } +} + +impl From<&'static str> for ElementId { + fn from(id: &'static str) -> Self { + Self(id.into()) + } +} diff --git a/crates/storybook2/src/collab_panel.rs b/crates/storybook2/src/collab_panel.rs index 944f6c5d9a..9efe3e88d3 100644 --- a/crates/storybook2/src/collab_panel.rs +++ b/crates/storybook2/src/collab_panel.rs @@ -1,7 +1,7 @@ use crate::theme::{theme, Theme}; use gpui3::{ - div, img, svg, view, AppContext, Context, Element, Interactive, IntoAnyElement, MouseButton, - ParentElement, ScrollState, SharedString, StyleHelpers, Styled, View, ViewContext, + div, img, svg, view, AppContext, Context, Element, ElementId, Interactive, IntoAnyElement, + MouseButton, ParentElement, ScrollState, SharedString, StyleHelpers, Styled, View, ViewContext, WindowContext, }; @@ -55,7 +55,7 @@ impl CollabPanel { //:: https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-parent-state // .group() // List Section Header - .child(self.list_section_header("#CRDB 🗃️", true, theme)) + .child(self.list_section_header(0, "#CRDB 🗃️", true, theme)) // List Item Large .child(self.list_item( "http://github.com/maxbrunsfeld.png?s=50", @@ -68,14 +68,14 @@ impl CollabPanel { .py_2() .flex() .flex_col() - .child(self.list_section_header("CHANNELS", true, theme)), + .child(self.list_section_header(1, "CHANNELS", true, theme)), ) .child( div() .py_2() .flex() .flex_col() - .child(self.list_section_header("CONTACTS", true, theme)) + .child(self.list_section_header(2, "CONTACTS", true, theme)) .children( std::iter::repeat_with(|| { vec![ @@ -120,11 +120,13 @@ impl CollabPanel { fn list_section_header( &self, + id: impl Into, label: impl IntoAnyElement, expanded: bool, theme: &Theme, ) -> impl Element { div() + .id(id) .h_7() .px_2() .flex() @@ -132,6 +134,8 @@ impl CollabPanel { .items_center() .hover() .fill(theme.lowest.base.active.background) + .active() + .fill(theme.highest.accent.default.background) .child(div().flex().gap_1().text_sm().child(label)) .child( div().flex().h_full().gap_1().items_center().child( diff --git a/crates/storybook2/src/theme.rs b/crates/storybook2/src/theme.rs index 540076b045..4e8b7c1adc 100644 --- a/crates/storybook2/src/theme.rs +++ b/crates/storybook2/src/theme.rs @@ -150,12 +150,15 @@ impl Element for Themed { fn layout( &mut self, state: &mut E::ViewState, + element_state: Option, cx: &mut ViewContext, - ) -> anyhow::Result<(LayoutId, Self::ElementState)> + ) -> (LayoutId, Self::ElementState) where Self: Sized, { - cx.with_state(self.theme.clone(), |cx| self.child.layout(state, cx)) + cx.with_state(self.theme.clone(), |cx| { + self.child.layout(state, element_state, cx) + }) } fn paint( @@ -164,32 +167,15 @@ impl Element for Themed { state: &mut Self::ViewState, frame_state: &mut Self::ElementState, cx: &mut ViewContext, - ) -> Result<()> - where + ) where Self: Sized, { cx.with_state(self.theme.clone(), |cx| { - self.child.paint(bounds, state, frame_state, cx) - }) + self.child.paint(bounds, state, frame_state, cx); + }); } } -// fn preferred_theme(cx: &AppContext) -> Theme { -// settings::get::(cx) -// .theme -// .deserialized_base_theme -// .lock() -// .get_or_insert_with(|| { -// let theme: Theme = -// serde_json::from_value(settings::get::(cx).theme.base_theme.clone()) -// .unwrap(); -// Box::new(theme) -// }) -// .downcast_ref::() -// .unwrap() -// .clone() -// } - pub fn theme<'a>(cx: &'a WindowContext) -> &'a Theme { cx.state() } diff --git a/crates/util/src/arc_cow.rs b/crates/util/src/arc_cow.rs index aa92fed8d0..2865130150 100644 --- a/crates/util/src/arc_cow.rs +++ b/crates/util/src/arc_cow.rs @@ -57,6 +57,18 @@ impl<'a> From> for ArcCow<'a, str> { } } +impl From> for ArcCow<'_, [T]> { + fn from(vec: Vec) -> Self { + ArcCow::Owned(Arc::from(vec)) + } +} + +impl<'a> From<&'a str> for ArcCow<'a, [u8]> { + fn from(s: &'a str) -> Self { + ArcCow::Borrowed(s.as_bytes()) + } +} + impl<'a, T: ?Sized + ToOwned> std::borrow::Borrow for ArcCow<'a, T> { fn borrow(&self) -> &T { match self {