From 0128079de0783c775940864e182b91fd5a4882a6 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 30 Oct 2023 20:36:48 +0100 Subject: [PATCH] WIP --- crates/gpui2/src/app.rs | 5 ++- crates/gpui2/src/element.rs | 2 +- crates/gpui2/src/interactive.rs | 15 ++++++- crates/gpui2/src/view.rs | 79 +++++++++++++-------------------- crates/gpui2/src/window.rs | 13 +++--- 5 files changed, 57 insertions(+), 57 deletions(-) diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index 0a09bb2ff834bfb71d784d6a537c4772d1eb37aa..0523609db305c305aeb624ab0d1b00c40a84ee96 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -15,7 +15,7 @@ pub use test_context::*; use crate::{ current_platform, image_cache::ImageCache, Action, AnyBox, AnyView, AppMetadata, AssetSource, ClipboardItem, Context, DispatchPhase, DisplayId, Executor, FocusEvent, FocusHandle, FocusId, - KeyBinding, Keymap, LayoutId, MainThread, MainThreadOnly, Pixels, Platform, Point, + KeyBinding, Keymap, LayoutId, MainThread, MainThreadOnly, Pixels, Platform, Point, Render, SharedString, SubscriberSet, Subscription, SvgRenderer, Task, TextStyle, TextStyleRefinement, TextSystem, View, Window, WindowContext, WindowHandle, WindowId, }; @@ -815,7 +815,7 @@ impl MainThread { /// Opens a new window with the given option and the root view returned by the given function. /// The function is invoked with a `WindowContext`, which can be used to interact with window-specific /// functionality. - pub fn open_window( + pub fn open_window( &mut self, options: crate::WindowOptions, build_root_view: impl FnOnce(&mut WindowContext) -> View + Send + 'static, @@ -898,6 +898,7 @@ impl DerefMut for GlobalLease { /// Contains state associated with an active drag operation, started by dragging an element /// within the window or by dragging into the app from the underlying platform. pub(crate) struct AnyDrag { + pub render: Box AnyElement<()>>, pub drag_handle_view: Option, pub cursor_offset: Point, pub state: AnyBox, diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index 6dc5bc0a93605292330d8d316fd65128f154c50d..a715ed30ee739cee6f0834be5be497415b0ff8b1 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -4,7 +4,7 @@ pub(crate) use smallvec::SmallVec; use std::{any::Any, mem}; pub trait Element { - type ElementState: 'static; + type ElementState: 'static + Send; fn id(&self) -> Option; diff --git a/crates/gpui2/src/interactive.rs b/crates/gpui2/src/interactive.rs index faa7d239757d43f6774610a4544b81f02f61fb17..43fd83a55f4a0e1af2d95077d503317c5bf94014 100644 --- a/crates/gpui2/src/interactive.rs +++ b/crates/gpui2/src/interactive.rs @@ -333,12 +333,19 @@ pub trait StatefulInteractive: StatelessInteractive { Some(Box::new(move |view_state, cursor_offset, cx| { let drag = listener(view_state, cx); let drag_handle_view = Some( - View::for_handle(cx.model().upgrade().unwrap(), move |view_state, cx| { - (drag.render_drag_handle)(view_state, cx) + cx.build_view(|cx| DragView { + model: cx.model().upgrade().unwrap(), + drag, }) .into_any(), ); AnyDrag { + render: { + let view = cx.view(); + Box::new(move |cx| { + view.update(cx, |view, cx| drag.render_drag_handle(view, cx)) + }) + }, drag_handle_view, cursor_offset, state: Box::new(drag.state), @@ -888,6 +895,10 @@ where } } +// impl Render for Drag { +// // fn render(&mut self, cx: ViewContext) -> +// } + #[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)] pub enum MouseButton { Left, diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index cacca8b91e2f4f7992bbbcc3dbfd5ea9c31cfbdb..630f2f98647a287b422975d9000d59154665230f 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -3,48 +3,31 @@ use crate::{ EntityId, LayoutId, Model, Pixels, Size, ViewContext, VisualContext, WeakModel, WindowContext, }; use anyhow::{Context, Result}; -use parking_lot::Mutex; -use std::{ - marker::PhantomData, - sync::{Arc, Weak}, -}; +use std::{marker::PhantomData, sync::Arc}; -pub struct View { - pub(crate) state: Model, - render: Arc) -> AnyElement + Send + 'static>>, +pub trait Render: 'static + Sized { + type Element: Element + 'static + Send; + + fn render(&mut self, cx: &mut ViewContext) -> Self::Element; } -impl View { - pub fn for_handle( - state: Model, - render: impl Fn(&mut V, &mut ViewContext<'_, '_, V>) -> E + Send + 'static, - ) -> View - where - E: Component, - { - View { - state, - render: Arc::new(Mutex::new( - move |state: &mut V, cx: &mut ViewContext<'_, '_, V>| render(state, cx).render(), - )), - } - } +pub struct View { + pub(crate) model: Model, } -impl View { +impl View { pub fn into_any(self) -> AnyView { AnyView(Arc::new(self)) } +} +impl View { pub fn downgrade(&self) -> WeakView { WeakView { - state: self.state.downgrade(), - render: Arc::downgrade(&self.render), + model: self.model.downgrade(), } } -} -impl View { pub fn update( &self, cx: &mut C, @@ -60,13 +43,12 @@ impl View { impl Clone for View { fn clone(&self) -> Self { Self { - state: self.state.clone(), - render: self.render.clone(), + model: self.model.clone(), } } } -impl Component for View { +impl Component for View { fn render(self) -> AnyElement { AnyElement::new(EraseViewState { view: self, @@ -75,11 +57,14 @@ impl Component for View Element<()> for View { +impl Element<()> for View +where + V: Render, +{ type ElementState = AnyElement; fn id(&self) -> Option { - Some(ElementId::View(self.state.entity_id)) + Some(ElementId::View(self.model.entity_id)) } fn initialize( @@ -89,7 +74,7 @@ impl Element<()> for View { cx: &mut ViewContext<()>, ) -> Self::ElementState { self.update(cx, |state, cx| { - let mut any_element = (self.render.lock())(state, cx); + let mut any_element = AnyElement::new(state.render(cx)); any_element.initialize(state, cx); any_element }) @@ -116,15 +101,13 @@ impl Element<()> for View { } pub struct WeakView { - pub(crate) state: WeakModel, - render: Weak) -> AnyElement + Send + 'static>>, + pub(crate) model: WeakModel, } impl WeakView { pub fn upgrade(&self) -> Option> { - let state = self.state.upgrade()?; - let render = self.render.upgrade()?; - Some(View { state, render }) + let model = self.model.upgrade()?; + Some(View { model }) } pub fn update( @@ -140,8 +123,7 @@ impl WeakView { impl Clone for WeakView { fn clone(&self) -> Self { Self { - state: self.state.clone(), - render: self.render.clone(), + model: self.model.clone(), } } } @@ -153,13 +135,13 @@ struct EraseViewState { unsafe impl Send for EraseViewState {} -impl Component for EraseViewState { +impl Component for EraseViewState { fn render(self) -> AnyElement { AnyElement::new(self) } } -impl Element for EraseViewState { +impl Element for EraseViewState { type ElementState = AnyBox; fn id(&self) -> Option { @@ -202,17 +184,20 @@ trait ViewObject: Send + Sync { fn paint(&self, bounds: Bounds, element: &mut AnyBox, cx: &mut WindowContext); } -impl ViewObject for View { +impl ViewObject for View +where + V: Render, +{ fn entity_id(&self) -> EntityId { - self.state.entity_id + self.model.entity_id } fn initialize(&self, cx: &mut WindowContext) -> AnyBox { cx.with_element_id(self.entity_id(), |_global_id, cx| { self.update(cx, |state, cx| { - let mut any_element = Box::new((self.render.lock())(state, cx)); + let mut any_element = Box::new(AnyElement::new(state.render(cx))); any_element.initialize(state, cx); - any_element as AnyBox + any_element }) }) } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 3d6a891dfe21097ab06d0f08666aaf793d012a64..86732cd21e0112438266ab119c1c9f1f541a3bc4 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -900,6 +900,9 @@ impl<'a, 'w> WindowContext<'a, 'w> { if let Some(drag_handle_view) = &mut active_drag.drag_handle_view { drag_handle_view.draw(available_space, cx); } + if let Some(render) = &mut active_drag.render { + (render)() + } cx.active_drag = Some(active_drag); }); }); @@ -1300,7 +1303,7 @@ impl VisualContext for WindowContext<'_, '_> { view: &View, update: impl FnOnce(&mut T, &mut Self::ViewContext<'_, '_, T>) -> R, ) -> Self::Result { - let mut lease = self.app.entities.lease(&view.state); + let mut lease = self.app.entities.lease(&view.model); let mut cx = ViewContext::mutable(&mut *self.app, &mut *self.window, view.downgrade()); let result = update(&mut *lease, &mut cx); cx.app.entities.end_lease(lease); @@ -1556,7 +1559,7 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> { } pub fn model(&self) -> WeakModel { - self.view.state.clone() + self.view.model.clone() } pub fn stack(&mut self, order: u32, f: impl FnOnce(&mut Self) -> R) -> R { @@ -1635,7 +1638,7 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> { ) -> Subscription { let window_handle = self.window.handle; self.app.release_listeners.insert( - self.view.state.entity_id, + self.view.model.entity_id, Box::new(move |this, cx| { let this = this.downcast_mut().expect("invalid entity type"); // todo!("are we okay with silently swallowing the error?") @@ -1668,7 +1671,7 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> { pub fn notify(&mut self) { self.window_cx.notify(); self.window_cx.app.push_effect(Effect::Notify { - emitter: self.view.state.entity_id, + emitter: self.view.model.entity_id, }); } @@ -1848,7 +1851,7 @@ where V::Event: Any + Send, { pub fn emit(&mut self, event: V::Event) { - let emitter = self.view.state.entity_id; + let emitter = self.view.model.entity_id; self.app.push_effect(Effect::Emit { emitter, event: Box::new(event),