From ce8533f83b9ca02fdf3b58bd612ce04812f9f94d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 12 Oct 2023 13:27:46 -0600 Subject: [PATCH] Checkpoint --- crates/gpui3/src/app/entity_map.rs | 8 +- crates/gpui3/src/view.rs | 12 +-- crates/gpui3_macros/src/derive_element.rs | 1 + crates/storybook2/src/story_selector.rs | 4 +- crates/storybook2/src/storybook2.rs | 1 + crates/ui2/src/components/assistant_panel.rs | 103 +++++++++---------- crates/ui2/src/components/chat_panel.rs | 57 +++++----- crates/ui2/src/components/multi_buffer.rs | 6 +- crates/ui2/src/components/panel.rs | 46 +++++---- crates/ui2/src/components/project_panel.rs | 15 +-- crates/ui2/src/components/workspace.rs | 89 ++++++---------- 11 files changed, 161 insertions(+), 181 deletions(-) diff --git a/crates/gpui3/src/app/entity_map.rs b/crates/gpui3/src/app/entity_map.rs index da170458cb..ce111c019d 100644 --- a/crates/gpui3/src/app/entity_map.rs +++ b/crates/gpui3/src/app/entity_map.rs @@ -102,10 +102,10 @@ impl core::ops::DerefMut for Lease { impl Drop for Lease { fn drop(&mut self) { - assert!( - self.entity.is_none(), - "Leases must be ended with EntityMap::end_lease" - ); + if self.entity.is_some() { + // We don't panic here, because other panics can cause us to drop the lease without ending it cleanly. + log::error!("Leases must be ended with EntityMap::end_lease") + } } } diff --git a/crates/gpui3/src/view.rs b/crates/gpui3/src/view.rs index 6af7a09df2..b22cb39e7f 100644 --- a/crates/gpui3/src/view.rs +++ b/crates/gpui3/src/view.rs @@ -33,8 +33,8 @@ pub fn view( render: impl Fn(&mut S, &mut ViewContext) -> E + Send + Sync + 'static, ) -> View where + E: IntoAnyElement, S: 'static + Send + Sync, - E: Element, { View { state, @@ -86,6 +86,8 @@ impl Element for View { } } +impl IdentifiedElement for View {} + struct EraseViewState { view: View, parent_view_state_type: PhantomData, @@ -137,11 +139,9 @@ where trait ViewObject: 'static + Send + Sync { fn entity_id(&self) -> EntityId; fn layout(&mut self, cx: &mut WindowContext) -> (LayoutId, AnyBox); - fn paint(&mut self, bounds: Bounds, element: &mut dyn Any, cx: &mut WindowContext); + fn paint(&mut self, bounds: Bounds, element: &mut AnyBox, cx: &mut WindowContext); } -impl IdentifiedElement for View {} - impl ViewObject for View { fn entity_id(&self) -> EntityId { self.state.id @@ -158,7 +158,7 @@ impl ViewObject for View { }) } - fn paint(&mut self, _: Bounds, element: &mut dyn Any, cx: &mut WindowContext) { + fn paint(&mut self, _: Bounds, element: &mut AnyBox, cx: &mut WindowContext) { cx.with_element_id(IdentifiedElement::element_id(self), |cx| { self.state.update(cx, |state, cx| { let element = element.downcast_mut::>().unwrap(); @@ -208,7 +208,7 @@ impl Element for AnyView { element: &mut AnyBox, cx: &mut ViewContext, ) { - self.view.lock().paint(bounds, element.as_mut(), cx) + self.view.lock().paint(bounds, element, cx) } } diff --git a/crates/gpui3_macros/src/derive_element.rs b/crates/gpui3_macros/src/derive_element.rs index 9dd232b450..32e8392dbd 100644 --- a/crates/gpui3_macros/src/derive_element.rs +++ b/crates/gpui3_macros/src/derive_element.rs @@ -56,6 +56,7 @@ pub fn derive_element(input: TokenStream) -> TokenStream { type ElementState = gpui3::AnyElement<#state_type>; fn element_id(&self) -> Option { + // todo!("What should element_id be here?") None } diff --git a/crates/storybook2/src/story_selector.rs b/crates/storybook2/src/story_selector.rs index 19bd267a10..7b85294c2b 100644 --- a/crates/storybook2/src/story_selector.rs +++ b/crates/storybook2/src/story_selector.rs @@ -7,7 +7,7 @@ use clap::ValueEnum; use gpui3::AnyElement; use strum::{EnumIter, EnumString, IntoEnumIterator}; -use ui::prelude::*; +use ui::{prelude::*, AssistantPanelStory}; #[derive(Debug, PartialEq, Eq, Clone, Copy, strum::Display, EnumString, EnumIter)] #[strum(serialize_all = "snake_case")] @@ -90,7 +90,7 @@ impl ComponentStory { Self::Toast => ui::ToastStory::new().into_any(), Self::Toolbar => ui::ToolbarStory::new().into_any(), Self::TrafficLights => ui::TrafficLightsStory::new().into_any(), - Self::Workspace => todo!(), + Self::Workspace => ui::workspace_story(cx).into_any().into_any(), } } } diff --git a/crates/storybook2/src/storybook2.rs b/crates/storybook2/src/storybook2.rs index 87c94a8ef6..36f7219eaa 100644 --- a/crates/storybook2/src/storybook2.rs +++ b/crates/storybook2/src/storybook2.rs @@ -94,6 +94,7 @@ fn main() { #[derive(Clone)] pub struct StoryWrapper { selector: StorySelector, + // story: theme: Theme, } diff --git a/crates/ui2/src/components/assistant_panel.rs b/crates/ui2/src/components/assistant_panel.rs index 18707fd29e..94fedca3a8 100644 --- a/crates/ui2/src/components/assistant_panel.rs +++ b/crates/ui2/src/components/assistant_panel.rs @@ -33,59 +33,50 @@ impl AssistantPanel { pub scroll_state: ScrollState, } - Panel::new( - self.scroll_state.clone(), - |_, payload| { - let payload = payload.downcast_ref::().unwrap(); - - vec![div() - .flex() - .flex_col() - .h_full() - .px_2() - .gap_2() - // Header - .child( - div() - .flex() - .justify_between() - .gap_2() - .child( - div() - .flex() - .child(IconButton::new(Icon::Menu)) - .child(Label::new("New Conversation")), - ) - .child( - div() - .flex() - .items_center() - .gap_px() - .child(IconButton::new(Icon::SplitMessage)) - .child(IconButton::new(Icon::Quote)) - .child(IconButton::new(Icon::MagicWand)) - .child(IconButton::new(Icon::Plus)) - .child(IconButton::new(Icon::Maximize)), - ), - ) - // Chat Body - .child( - div() - .w_full() - .flex() - .flex_col() - .gap_3() - .overflow_y_scroll(payload.scroll_state.clone()) - .child(Label::new("Is this thing on?")), - ) - .into_any()] - }, - Box::new(PanelPayload { - scroll_state: self.scroll_state.clone(), - }), - ) - .side(self.current_side) - .width(AbsoluteLength::Rems(rems(32.))) + Panel::new(self.scroll_state.clone()) + .children(vec![div() + .flex() + .flex_col() + .h_full() + .px_2() + .gap_2() + // Header + .child( + div() + .flex() + .justify_between() + .gap_2() + .child( + div() + .flex() + .child(IconButton::new(Icon::Menu)) + .child(Label::new("New Conversation")), + ) + .child( + div() + .flex() + .items_center() + .gap_px() + .child(IconButton::new(Icon::SplitMessage)) + .child(IconButton::new(Icon::Quote)) + .child(IconButton::new(Icon::MagicWand)) + .child(IconButton::new(Icon::Plus)) + .child(IconButton::new(Icon::Maximize)), + ), + ) + // Chat Body + .child( + div() + .w_full() + .flex() + .flex_col() + .gap_3() + .overflow_y_scroll(self.scroll_state.clone()) + .child(Label::new("Is this thing on?")), + ) + .into_any()]) + .side(self.current_side) + .width(AbsoluteLength::Rems(rems(32.))) } } @@ -110,7 +101,11 @@ mod stories { } } - fn render(&mut self, _view: &mut S, cx: &mut ViewContext) -> impl Element { + fn render( + &mut self, + _view: &mut S, + cx: &mut ViewContext, + ) -> impl Element { Story::container(cx) .child(Story::title_for::<_, AssistantPanel>(cx)) .child(Story::label(cx, "Default")) diff --git a/crates/ui2/src/components/chat_panel.rs b/crates/ui2/src/components/chat_panel.rs index d6fe01ce8e..45a62e207a 100644 --- a/crates/ui2/src/components/chat_panel.rs +++ b/crates/ui2/src/components/chat_panel.rs @@ -20,7 +20,7 @@ impl ChatPanel { } } - pub fn with_messages(mut self, messages: Vec>) -> Self { + pub fn messages(mut self, messages: Vec>) -> Self { self.messages = messages; self } @@ -130,39 +130,36 @@ mod stories { } } - fn render(&mut self, _view: &mut S, cx: &mut ViewContext) -> impl Element { + fn render( + &mut self, + _view: &mut S, + cx: &mut ViewContext, + ) -> impl Element { Story::container(cx) .child(Story::title_for::<_, ChatPanel>(cx)) .child(Story::label(cx, "Default")) - .child(Panel::new( - ScrollState::default(), - |_, _| vec![ChatPanel::new(ScrollState::default()).into_any()], - Box::new(()), - )) + .child( + Panel::new(ScrollState::default()) + .child(ChatPanel::new(ScrollState::default())), + ) .child(Story::label(cx, "With Mesages")) - .child(Panel::new( - ScrollState::default(), - |_, _| { - vec![ChatPanel::new(ScrollState::default()) - .with_messages(vec![ - ChatMessage::new( - "osiewicz".to_string(), - "is this thing on?".to_string(), - DateTime::parse_from_rfc3339("2023-09-27T15:40:52.707Z") - .unwrap() - .naive_local(), - ), - ChatMessage::new( - "maxdeviant".to_string(), - "Reading you loud and clear!".to_string(), - DateTime::parse_from_rfc3339("2023-09-28T15:40:52.707Z") - .unwrap() - .naive_local(), - ), - ]) - .into_any()] - }, - Box::new(()), + .child(Panel::new(ScrollState::default()).child( + ChatPanel::new(ScrollState::default()).messages(vec![ + ChatMessage::new( + "osiewicz".to_string(), + "is this thing on?".to_string(), + DateTime::parse_from_rfc3339("2023-09-27T15:40:52.707Z") + .unwrap() + .naive_local(), + ), + ChatMessage::new( + "maxdeviant".to_string(), + "Reading you loud and clear!".to_string(), + DateTime::parse_from_rfc3339("2023-09-28T15:40:52.707Z") + .unwrap() + .naive_local(), + ), + ]), )) } } diff --git a/crates/ui2/src/components/multi_buffer.rs b/crates/ui2/src/components/multi_buffer.rs index b18e85caea..31e6faa3bc 100644 --- a/crates/ui2/src/components/multi_buffer.rs +++ b/crates/ui2/src/components/multi_buffer.rs @@ -62,7 +62,11 @@ mod stories { } } - fn render(&mut self, _view: &mut S, cx: &mut ViewContext) -> impl Element { + fn render( + &mut self, + _view: &mut S, + cx: &mut ViewContext, + ) -> impl Element { let theme = theme(cx); Story::container(cx) diff --git a/crates/ui2/src/components/panel.rs b/crates/ui2/src/components/panel.rs index edb74c01d2..32ecdd1448 100644 --- a/crates/ui2/src/components/panel.rs +++ b/crates/ui2/src/components/panel.rs @@ -1,6 +1,7 @@ use std::marker::PhantomData; -use gpui3::AbsoluteLength; +use gpui3::{AbsoluteLength, AnyElement}; +use smallvec::SmallVec; use crate::{prelude::*, theme}; use crate::{token, v_stack}; @@ -47,16 +48,11 @@ pub struct Panel { allowed_sides: PanelAllowedSides, initial_width: AbsoluteLength, width: Option, - children: HackyChildren, - payload: HackyChildrenPayload, + children: SmallVec<[AnyElement; 2]>, } impl Panel { - pub fn new( - scroll_state: ScrollState, - children: HackyChildren, - payload: HackyChildrenPayload, - ) -> Self { + pub fn new(scroll_state: ScrollState) -> Self { let token = token(); Self { @@ -66,8 +62,7 @@ impl Panel { allowed_sides: PanelAllowedSides::default(), initial_width: token.default_panel_size, width: None, - children, - payload, + children: SmallVec::new(), } } @@ -140,7 +135,15 @@ impl Panel { } } - panel_base.children_any((self.children)(cx, self.payload.as_ref())) + panel_base.children(self.children.drain(..)) + } +} + +impl ParentElement for Panel { + type State = S; + + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { + &mut self.children } } @@ -165,20 +168,21 @@ mod stories { } } - fn render(&mut self, _view: &mut S, cx: &mut ViewContext) -> impl Element { + fn render( + &mut self, + _view: &mut S, + cx: &mut ViewContext, + ) -> impl Element { Story::container(cx) .child(Story::title_for::<_, Panel>(cx)) .child(Story::label(cx, "Default")) - .child(Panel::new( - ScrollState::default(), - |_, _| { - vec![div() + .child( + Panel::new(ScrollState::default()).child( + div() .overflow_y_scroll(ScrollState::default()) - .children((0..100).map(|ix| Label::new(format!("Item {}", ix + 1)))) - .into_any()] - }, - Box::new(()), - )) + .children((0..100).map(|ix| Label::new(format!("Item {}", ix + 1)))), + ), + ) } } } diff --git a/crates/ui2/src/components/project_panel.rs b/crates/ui2/src/components/project_panel.rs index 0961bc907b..66ec6fbf01 100644 --- a/crates/ui2/src/components/project_panel.rs +++ b/crates/ui2/src/components/project_panel.rs @@ -78,15 +78,18 @@ mod stories { } } - fn render(&mut self, _view: &mut S, cx: &mut ViewContext) -> impl Element { + fn render( + &mut self, + _view: &mut S, + cx: &mut ViewContext, + ) -> impl Element { Story::container(cx) .child(Story::title_for::<_, ProjectPanel>(cx)) .child(Story::label(cx, "Default")) - .child(Panel::new( - ScrollState::default(), - |_, _| vec![ProjectPanel::new(ScrollState::default()).into_any()], - Box::new(()), - )) + .child( + Panel::new(ScrollState::default()) + .child(ProjectPanel::new(ScrollState::default())), + ) } } } diff --git a/crates/ui2/src/components/workspace.rs b/crates/ui2/src/components/workspace.rs index 9f75c4edad..2a46fdde1f 100644 --- a/crates/ui2/src/components/workspace.rs +++ b/crates/ui2/src/components/workspace.rs @@ -244,27 +244,17 @@ impl Workspace { .border_color(theme.lowest.base.default.border) .children( Some( - Panel::new( - self.left_panel_scroll_state.clone(), - |_, payload| { - vec![ProjectPanel::new(ScrollState::default()).into_any()] - }, - Box::new(()), - ) - .side(PanelSide::Left), + Panel::new(self.left_panel_scroll_state.clone()) + .side(PanelSide::Left) + .child(ProjectPanel::new(ScrollState::default())), ) .filter(|_| workspace_state.is_project_panel_open()), ) .children( Some( - Panel::new( - self.left_panel_scroll_state.clone(), - |_, payload| { - vec![CollabPanel::new(ScrollState::default()).into_any()] - }, - Box::new(()), - ) - .side(PanelSide::Left), + Panel::new(self.left_panel_scroll_state.clone()) + .child(CollabPanel::new(ScrollState::default())) + .side(PanelSide::Left), ) .filter(|_| workspace_state.is_collab_panel_open()), ) @@ -285,57 +275,42 @@ impl Workspace { ) .children( Some( - Panel::new( - self.bottom_panel_scroll_state.clone(), - |_, _| vec![Terminal::new().into_any()], - Box::new(()), - ) - .allowed_sides(PanelAllowedSides::BottomOnly) - .side(PanelSide::Bottom), + Panel::new(self.bottom_panel_scroll_state.clone()) + .child(Terminal::new()) + .allowed_sides(PanelAllowedSides::BottomOnly) + .side(PanelSide::Bottom), ) .filter(|_| workspace_state.show_terminal.load(Ordering::SeqCst)), ), ) .children( Some( - Panel::new( - self.right_panel_scroll_state.clone(), - |_, payload| { - vec![ChatPanel::new(ScrollState::default()) - .with_messages(vec![ - ChatMessage::new( - "osiewicz".to_string(), - "is this thing on?".to_string(), - DateTime::parse_from_rfc3339( - "2023-09-27T15:40:52.707Z", - ) - .unwrap() - .naive_local(), - ), - ChatMessage::new( - "maxdeviant".to_string(), - "Reading you loud and clear!".to_string(), - DateTime::parse_from_rfc3339( - "2023-09-28T15:40:52.707Z", - ) - .unwrap() - .naive_local(), - ), - ]) - .into_any()] - }, - Box::new(()), - ) - .side(PanelSide::Right), + Panel::new(self.right_panel_scroll_state.clone()) + .side(PanelSide::Right) + .child(ChatPanel::new(ScrollState::default()).messages(vec![ + ChatMessage::new( + "osiewicz".to_string(), + "is this thing on?".to_string(), + DateTime::parse_from_rfc3339("2023-09-27T15:40:52.707Z") + .unwrap() + .naive_local(), + ), + ChatMessage::new( + "maxdeviant".to_string(), + "Reading you loud and clear!".to_string(), + DateTime::parse_from_rfc3339("2023-09-28T15:40:52.707Z") + .unwrap() + .naive_local(), + ), + ])), ) .filter(|_| workspace_state.is_chat_panel_open()), ) .children( - Some(Panel::new( - self.right_panel_scroll_state.clone(), - |_, _| vec![AssistantPanel::new().into_any()], - Box::new(()), - )) + Some( + Panel::new(self.right_panel_scroll_state.clone()) + .child(AssistantPanel::new()), + ) .filter(|_| workspace_state.is_assistant_panel_open()), ), )