@@ -4,7 +4,7 @@ use crate::{
ViewContext, VisualContext, WeakModel, WindowContext,
};
use anyhow::{Context, Result};
-use std::{any::TypeId, marker::PhantomData, sync::Arc};
+use std::{any::TypeId, marker::PhantomData};
pub trait Render: 'static + Sized {
type Element: Element<Self> + 'static + Send;
@@ -18,12 +18,6 @@ pub struct View<V> {
impl<V> Sealed for View<V> {}
-impl<V: Render> View<V> {
- pub fn into_any(self) -> AnyView {
- AnyView(Arc::new(self))
- }
-}
-
impl<V: 'static> Entity<V> for View<V> {
type Weak = WeakView<V>;
@@ -265,94 +259,110 @@ where
}
}
-#[derive(Clone)]
-pub struct AnyView(Arc<dyn ViewObject>);
+#[derive(Clone, Debug)]
+pub struct AnyView {
+ model: AnyModel,
+ initialize: fn(&Self, &mut WindowContext) -> AnyBox,
+ layout: fn(&Self, &mut AnyBox, &mut WindowContext) -> LayoutId,
+ paint: fn(&Self, &mut AnyBox, &mut WindowContext),
+}
impl AnyView {
- pub fn downcast<V: 'static + Send>(self) -> Result<View<V>, AnyView> {
- self.0
- .model()
- .downcast()
- .map(|model| View { model })
- .map_err(|_| self)
+ pub fn downcast<T: 'static>(self) -> Result<View<T>, Self> {
+ match self.model.downcast() {
+ Ok(model) => Ok(View { model }),
+ Err(model) => Err(Self {
+ model,
+ initialize: self.initialize,
+ layout: self.layout,
+ paint: self.paint,
+ }),
+ }
}
pub(crate) fn entity_type(&self) -> TypeId {
- self.0.entity_type()
+ self.model.entity_type
}
pub(crate) fn draw(&self, available_space: Size<AvailableSpace>, cx: &mut WindowContext) {
- let mut rendered_element = self.0.initialize(cx);
- let layout_id = self.0.layout(&mut rendered_element, cx);
+ let mut rendered_element = (self.initialize)(self, cx);
+ let layout_id = (self.layout)(self, &mut rendered_element, cx);
cx.window
.layout_engine
.compute_layout(layout_id, available_space);
- let bounds = cx.window.layout_engine.layout_bounds(layout_id);
- self.0.paint(bounds, &mut rendered_element, cx);
+ (self.paint)(self, &mut rendered_element, cx);
}
}
-impl<ParentV: 'static> Component<ParentV> for AnyView {
- fn render(self) -> AnyElement<ParentV> {
- AnyElement::new(EraseAnyViewState {
- view: self,
- parent_view_state_type: PhantomData,
- })
+impl<V: 'static> Component<V> for AnyView {
+ fn render(self) -> AnyElement<V> {
+ AnyElement::new(self)
+ }
+}
+
+impl<V: Render> From<View<V>> for AnyView {
+ fn from(value: View<V>) -> Self {
+ AnyView {
+ model: value.model.into_any(),
+ initialize: |view, cx| {
+ cx.with_element_id(view.model.entity_id, |_, cx| {
+ let view = view.clone().downcast::<V>().unwrap();
+ Box::new(AnyElement::new(
+ view.update(cx, |view, cx| Render::render(view, cx)),
+ ))
+ })
+ },
+ layout: |view, element, cx| {
+ cx.with_element_id(view.model.entity_id, |_, cx| {
+ let view = view.clone().downcast::<V>().unwrap();
+ let element = element.downcast_mut::<AnyElement<V>>().unwrap();
+ view.update(cx, |view, cx| element.layout(view, cx))
+ })
+ },
+ paint: |view, element, cx| {
+ cx.with_element_id(view.model.entity_id, |_, cx| {
+ let view = view.clone().downcast::<V>().unwrap();
+ let element = element.downcast_mut::<AnyElement<V>>().unwrap();
+ view.update(cx, |view, cx| element.paint(view, cx))
+ })
+ },
+ }
}
}
-impl Element<()> for AnyView {
+impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
type ElementState = AnyBox;
- fn id(&self) -> Option<crate::ElementId> {
- Some(ElementId::View(self.0.entity_id()))
+ fn id(&self) -> Option<ElementId> {
+ Some(self.model.entity_id.into())
}
fn initialize(
&mut self,
- _: &mut (),
- _: Option<Self::ElementState>,
- cx: &mut ViewContext<()>,
+ _view_state: &mut ParentViewState,
+ _element_state: Option<Self::ElementState>,
+ cx: &mut ViewContext<ParentViewState>,
) -> Self::ElementState {
- self.0.initialize(cx)
+ (self.initialize)(self, cx)
}
fn layout(
&mut self,
- _: &mut (),
- element: &mut Self::ElementState,
- cx: &mut ViewContext<()>,
+ _view_state: &mut ParentViewState,
+ rendered_element: &mut Self::ElementState,
+ cx: &mut ViewContext<ParentViewState>,
) -> LayoutId {
- self.0.layout(element, cx)
+ (self.layout)(self, rendered_element, cx)
}
fn paint(
&mut self,
- bounds: Bounds<Pixels>,
- _: &mut (),
- element: &mut AnyBox,
- cx: &mut ViewContext<()>,
+ _bounds: Bounds<Pixels>,
+ _view_state: &mut ParentViewState,
+ rendered_element: &mut Self::ElementState,
+ cx: &mut ViewContext<ParentViewState>,
) {
- self.0.paint(bounds, element, cx)
- }
-}
-
-impl std::fmt::Debug for AnyView {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- self.0.debug(f)
- }
-}
-
-struct EraseAnyViewState<ParentViewState> {
- view: AnyView,
- parent_view_state_type: PhantomData<ParentViewState>,
-}
-
-unsafe impl<ParentV> Send for EraseAnyViewState<ParentV> {}
-
-impl<ParentV: 'static> Component<ParentV> for EraseAnyViewState<ParentV> {
- fn render(self) -> AnyElement<ParentV> {
- AnyElement::new(self)
+ (self.paint)(self, rendered_element, cx)
}
}
@@ -367,39 +377,3 @@ where
(self)(cx)
}
}
-
-impl<ParentV: 'static> Element<ParentV> for EraseAnyViewState<ParentV> {
- type ElementState = AnyBox;
-
- fn id(&self) -> Option<crate::ElementId> {
- Element::id(&self.view)
- }
-
- fn initialize(
- &mut self,
- _: &mut ParentV,
- _: Option<Self::ElementState>,
- cx: &mut ViewContext<ParentV>,
- ) -> Self::ElementState {
- self.view.0.initialize(cx)
- }
-
- fn layout(
- &mut self,
- _: &mut ParentV,
- element: &mut Self::ElementState,
- cx: &mut ViewContext<ParentV>,
- ) -> LayoutId {
- self.view.0.layout(element, cx)
- }
-
- fn paint(
- &mut self,
- bounds: Bounds<Pixels>,
- _: &mut ParentV,
- element: &mut Self::ElementState,
- cx: &mut ViewContext<ParentV>,
- ) {
- self.view.0.paint(bounds, element, cx)
- }
-}
@@ -28,17 +28,17 @@ pub enum ElementStory {
impl ElementStory {
pub fn story(&self, cx: &mut WindowContext) -> AnyView {
match self {
- Self::Colors => cx.build_view(|_| ColorsStory).into_any(),
- Self::Avatar => cx.build_view(|_| AvatarStory).into_any(),
- Self::Button => cx.build_view(|_| ButtonStory).into_any(),
- Self::Details => cx.build_view(|_| DetailsStory).into_any(),
- Self::Focus => FocusStory::view(cx).into_any(),
- Self::Icon => cx.build_view(|_| IconStory).into_any(),
- Self::Input => cx.build_view(|_| InputStory).into_any(),
- Self::Label => cx.build_view(|_| LabelStory).into_any(),
- Self::Scroll => ScrollStory::view(cx).into_any(),
- Self::Text => TextStory::view(cx).into_any(),
- Self::ZIndex => cx.build_view(|_| ZIndexStory).into_any(),
+ Self::Colors => cx.build_view(|_| ColorsStory).into(),
+ Self::Avatar => cx.build_view(|_| AvatarStory).into(),
+ Self::Button => cx.build_view(|_| ButtonStory).into(),
+ Self::Details => cx.build_view(|_| DetailsStory).into(),
+ Self::Focus => FocusStory::view(cx).into(),
+ Self::Icon => cx.build_view(|_| IconStory).into(),
+ Self::Input => cx.build_view(|_| InputStory).into(),
+ Self::Label => cx.build_view(|_| LabelStory).into(),
+ Self::Scroll => ScrollStory::view(cx).into(),
+ Self::Text => TextStory::view(cx).into(),
+ Self::ZIndex => cx.build_view(|_| ZIndexStory).into(),
}
}
}
@@ -77,32 +77,32 @@ pub enum ComponentStory {
impl ComponentStory {
pub fn story(&self, cx: &mut WindowContext) -> AnyView {
match self {
- Self::AssistantPanel => cx.build_view(|_| ui::AssistantPanelStory).into_any(),
- Self::Buffer => cx.build_view(|_| ui::BufferStory).into_any(),
- Self::Breadcrumb => cx.build_view(|_| ui::BreadcrumbStory).into_any(),
- Self::ChatPanel => cx.build_view(|_| ui::ChatPanelStory).into_any(),
- Self::CollabPanel => cx.build_view(|_| ui::CollabPanelStory).into_any(),
- Self::CommandPalette => cx.build_view(|_| ui::CommandPaletteStory).into_any(),
- Self::ContextMenu => cx.build_view(|_| ui::ContextMenuStory).into_any(),
- Self::Facepile => cx.build_view(|_| ui::FacepileStory).into_any(),
- Self::Keybinding => cx.build_view(|_| ui::KeybindingStory).into_any(),
- Self::LanguageSelector => cx.build_view(|_| ui::LanguageSelectorStory).into_any(),
- Self::MultiBuffer => cx.build_view(|_| ui::MultiBufferStory).into_any(),
- Self::NotificationsPanel => cx.build_view(|cx| ui::NotificationsPanelStory).into_any(),
- Self::Palette => cx.build_view(|cx| ui::PaletteStory).into_any(),
- Self::Panel => cx.build_view(|cx| ui::PanelStory).into_any(),
- Self::ProjectPanel => cx.build_view(|_| ui::ProjectPanelStory).into_any(),
- Self::RecentProjects => cx.build_view(|_| ui::RecentProjectsStory).into_any(),
- Self::Tab => cx.build_view(|_| ui::TabStory).into_any(),
- Self::TabBar => cx.build_view(|_| ui::TabBarStory).into_any(),
- Self::Terminal => cx.build_view(|_| ui::TerminalStory).into_any(),
- Self::ThemeSelector => cx.build_view(|_| ui::ThemeSelectorStory).into_any(),
- Self::Toast => cx.build_view(|_| ui::ToastStory).into_any(),
- Self::Toolbar => cx.build_view(|_| ui::ToolbarStory).into_any(),
- Self::TrafficLights => cx.build_view(|_| ui::TrafficLightsStory).into_any(),
- Self::Copilot => cx.build_view(|_| ui::CopilotModalStory).into_any(),
- Self::TitleBar => ui::TitleBarStory::view(cx).into_any(),
- Self::Workspace => ui::WorkspaceStory::view(cx).into_any(),
+ Self::AssistantPanel => cx.build_view(|_| ui::AssistantPanelStory).into(),
+ Self::Buffer => cx.build_view(|_| ui::BufferStory).into(),
+ Self::Breadcrumb => cx.build_view(|_| ui::BreadcrumbStory).into(),
+ Self::ChatPanel => cx.build_view(|_| ui::ChatPanelStory).into(),
+ Self::CollabPanel => cx.build_view(|_| ui::CollabPanelStory).into(),
+ Self::CommandPalette => cx.build_view(|_| ui::CommandPaletteStory).into(),
+ Self::ContextMenu => cx.build_view(|_| ui::ContextMenuStory).into(),
+ Self::Facepile => cx.build_view(|_| ui::FacepileStory).into(),
+ Self::Keybinding => cx.build_view(|_| ui::KeybindingStory).into(),
+ Self::LanguageSelector => cx.build_view(|_| ui::LanguageSelectorStory).into(),
+ Self::MultiBuffer => cx.build_view(|_| ui::MultiBufferStory).into(),
+ Self::NotificationsPanel => cx.build_view(|cx| ui::NotificationsPanelStory).into(),
+ Self::Palette => cx.build_view(|cx| ui::PaletteStory).into(),
+ Self::Panel => cx.build_view(|cx| ui::PanelStory).into(),
+ Self::ProjectPanel => cx.build_view(|_| ui::ProjectPanelStory).into(),
+ Self::RecentProjects => cx.build_view(|_| ui::RecentProjectsStory).into(),
+ Self::Tab => cx.build_view(|_| ui::TabStory).into(),
+ Self::TabBar => cx.build_view(|_| ui::TabBarStory).into(),
+ Self::Terminal => cx.build_view(|_| ui::TerminalStory).into(),
+ Self::ThemeSelector => cx.build_view(|_| ui::ThemeSelectorStory).into(),
+ Self::Toast => cx.build_view(|_| ui::ToastStory).into(),
+ Self::Toolbar => cx.build_view(|_| ui::ToolbarStory).into(),
+ Self::TrafficLights => cx.build_view(|_| ui::TrafficLightsStory).into(),
+ Self::Copilot => cx.build_view(|_| ui::CopilotModalStory).into(),
+ Self::TitleBar => ui::TitleBarStory::view(cx).into(),
+ Self::Workspace => ui::WorkspaceStory::view(cx).into(),
}
}
}
@@ -149,7 +149,7 @@ impl StorySelector {
match self {
Self::Element(element_story) => element_story.story(cx),
Self::Component(component_story) => component_story.story(cx),
- Self::KitchenSink => KitchenSinkStory::view(cx).into_any(),
+ Self::KitchenSink => KitchenSinkStory::view(cx).into(),
}
}
}