diff --git a/crates/gpui3/src/app.rs b/crates/gpui3/src/app.rs index a6ec39244b3f149ea1bc6206543408af40516a8f..ce6d7d88dc7f2a7021e0ee52d34e7f10b5d921b8 100644 --- a/crates/gpui3/src/app.rs +++ b/crates/gpui3/src/app.rs @@ -3,31 +3,41 @@ use crate::{ WindowContext, WindowHandle, WindowId, }; use anyhow::{anyhow, Result}; +use async_task::Runnable; +use futures::Future; +use parking_lot::RwLock; use slotmap::SlotMap; -use std::{any::Any, cell::RefCell, marker::PhantomData, rc::Rc, sync::Arc}; +use std::{ + any::Any, + marker::PhantomData, + sync::{Arc, Weak}, +}; #[derive(Clone)] -pub struct App(Rc>); +pub struct App(Arc>>); + +pub struct MainThread; impl App { pub fn new() -> Self { - Self(Rc::new(RefCell::new(AppContext::new(current_platform())))) + Self(Arc::new(RwLock::new(AppContext::new(current_platform())))) } pub fn run(self, on_finish_launching: F) where - F: 'static + FnOnce(&mut AppContext), + F: 'static + FnOnce(&mut AppContext), { - let platform = self.0.borrow().platform().clone(); platform.run(Box::new(move || { - let mut cx = self.0.borrow_mut(); + let mut cx = self.0.write(); on_finish_launching(&mut *cx); })); } } -pub struct AppContext { - platform: Rc, +pub struct AppContext { + this: Weak>, + thread: PhantomData, + platform: Box, text_system: Arc, pub(crate) unit_entity_id: EntityId, pub(crate) entities: SlotMap>>, @@ -36,13 +46,40 @@ pub struct AppContext { pub(crate) layout_id_buffer: Vec, } -impl AppContext { - pub fn new(platform: Rc) -> Self { +impl AppContext<()> { + pub fn run_on_main( + &self, + to_call: F, + ) -> Result> + where + F: Fn(&mut AppContext) -> T + Send + Sync, + { + let dispatcher = self.platform().dispatcher(); + if dispatcher.is_main_thread() { + } else { + let future = async move { + // let cx = unsafe { }; + }; + let schedule = move |runnable: Runnable| dispatcher.run_on_main_thread(runnable); + + let (runnable, task) = async_task::spawn_local(); + runnable.schedule(); + } + + let (runnable, task) = async_task::spawn_local(future, schedule); + runnable.schedule(); + task + } +} + +impl AppContext { + pub fn new(platform: Arc) -> Self { let text_system = Arc::new(TextSystem::new(platform.text_system())); let mut entities = SlotMap::with_key(); let unit_entity_id = entities.insert(Some(Box::new(()) as Box)); AppContext { + thread: PhantomData, platform, text_system, unit_entity_id, @@ -54,11 +91,7 @@ impl AppContext { #[cfg(any(test, feature = "test"))] pub fn test() -> Self { - Self::new(Rc::new(super::TestPlatform::new())) - } - - pub fn platform(&self) -> &Rc { - &self.platform + Self::new(Arc::new(super::TestPlatform::new())) } pub fn text_system(&self) -> &Arc { @@ -105,8 +138,14 @@ impl AppContext { } } -impl Context for AppContext { - type EntityContext<'a, 'w, T: 'static> = ModelContext<'a, T>; +impl AppContext { + pub fn platform(&self) -> &dyn Platform { + self.platform.as_ref() + } +} + +impl Context for AppContext { + type EntityContext<'a, 'w, T: 'static> = ModelContext<'a, Thread, T>; fn entity( &mut self, @@ -139,14 +178,14 @@ impl Context for AppContext { } } -pub struct ModelContext<'a, T> { - app: Reference<'a, AppContext>, +pub struct ModelContext<'a, Thread: 'static, T> { + app: Reference<'a, AppContext>, entity_type: PhantomData, entity_id: EntityId, } -impl<'a, T: 'static> ModelContext<'a, T> { - pub(crate) fn mutable(app: &'a mut AppContext, entity_id: EntityId) -> Self { +impl<'a, Thread, T: 'static> ModelContext<'a, Thread, T> { + pub(crate) fn mutable(app: &'a mut AppContext, entity_id: EntityId) -> Self { Self { app: Reference::Mutable(app), entity_type: PhantomData, @@ -154,7 +193,7 @@ impl<'a, T: 'static> ModelContext<'a, T> { } } - fn immutable(app: &'a AppContext, entity_id: EntityId) -> Self { + fn immutable(app: &'a AppContext, entity_id: EntityId) -> Self { Self { app: Reference::Immutable(app), entity_type: PhantomData, @@ -180,9 +219,8 @@ impl<'a, T: 'static> ModelContext<'a, T> { } } -impl<'a, T: 'static> Context for ModelContext<'a, T> { - type EntityContext<'b, 'c, U: 'static> = ModelContext<'b, U>; - +impl<'a, Thread, T: 'static> Context for ModelContext<'a, Thread, T> { + type EntityContext<'b, 'c, U: 'static> = ModelContext<'b, Thread, U>; fn entity( &mut self, build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, U>) -> U, diff --git a/crates/gpui3/src/element.rs b/crates/gpui3/src/element.rs index 214ce41d2b950dcd1c1585101ed4788c4ff11c86..2ba202f7a968ec9c9ae924fb34fd528775712edb 100644 --- a/crates/gpui3/src/element.rs +++ b/crates/gpui3/src/element.rs @@ -1,4 +1,4 @@ -use super::{Handle, Layout, LayoutId, Pixels, Point, Result, ViewContext}; +use super::{Layout, LayoutId, Pixels, Point, Result, ViewContext}; pub(crate) use smallvec::SmallVec; use std::{any::Any, cell::RefCell, marker::PhantomData, rc::Rc}; diff --git a/crates/gpui3/src/platform.rs b/crates/gpui3/src/platform.rs index f75f806dc0bf7c6df16004e2c47c522a1046e541..587e75569716ddfe762d650f9ed910082038988a 100644 --- a/crates/gpui3/src/platform.rs +++ b/crates/gpui3/src/platform.rs @@ -36,12 +36,12 @@ pub use mac::*; pub use test::*; #[cfg(target_os = "macos")] -pub(crate) fn current_platform() -> Rc { +pub(crate) fn current_platform() -> Arc { Rc::new(MacPlatform::new()) } pub trait Platform { - fn executor(&self) -> Rc; + fn dispatcher(&self) -> Arc; fn text_system(&self) -> Arc; fn run(&self, on_finish_launching: Box); diff --git a/crates/gpui3/src/view.rs b/crates/gpui3/src/view.rs new file mode 100644 index 0000000000000000000000000000000000000000..887963742e48a03c0caa142da487f61bbd6a7f52 --- /dev/null +++ b/crates/gpui3/src/view.rs @@ -0,0 +1,143 @@ +use crate::{ + AnyElement, Element, Handle, IntoAnyElement, Layout, LayoutId, Result, ViewContext, + WindowContext, +}; +use std::{any::Any, cell::RefCell, marker::PhantomData, rc::Rc}; + +pub struct View { + state: Handle, + render: Rc) -> AnyElement>, + parent_state_type: PhantomData

, +} + +impl Clone for View { + fn clone(&self) -> Self { + Self { + state: self.state.clone(), + render: self.render.clone(), + parent_state_type: PhantomData, + } + } +} + +pub type RootView = View; + +pub fn view>( + state: Handle, + render: impl 'static + Fn(&mut S, &mut ViewContext) -> E, +) -> View { + View { + state, + render: Rc::new(move |state, cx| render(state, cx).into_any()), + parent_state_type: PhantomData, + } +} + +impl View { + pub fn into_any(self) -> AnyView { + AnyView { + view: Rc::new(RefCell::new(self)), + parent_state_type: PhantomData, + } + } +} + +impl Element for View { + type State = P; + type FrameState = AnyElement; + + fn layout( + &mut self, + _: &mut Self::State, + cx: &mut ViewContext, + ) -> Result<(LayoutId, Self::FrameState)> { + self.state.update(cx, |state, cx| { + let mut element = (self.render)(state, cx); + let layout_id = element.layout(state, cx)?; + Ok((layout_id, element)) + }) + } + + fn paint( + &mut self, + layout: Layout, + _: &mut Self::State, + element: &mut Self::FrameState, + cx: &mut ViewContext, + ) -> Result<()> { + self.state + .update(cx, |state, cx| element.paint(state, None, cx)) + } +} + +trait ViewObject { + fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box)>; + fn paint( + &mut self, + layout: Layout, + element: &mut dyn Any, + cx: &mut WindowContext, + ) -> Result<()>; +} + +impl ViewObject for View { + fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box)> { + self.state.update(cx, |state, cx| { + let mut element = (self.render)(state, cx); + let layout_id = element.layout(state, cx)?; + let element = Box::new(element) as Box; + Ok((layout_id, element)) + }) + } + + fn paint( + &mut self, + layout: Layout, + element: &mut dyn Any, + cx: &mut WindowContext, + ) -> Result<()> { + self.state.update(cx, |state, cx| { + element + .downcast_mut::>() + .unwrap() + .paint(state, None, cx) + }) + } +} + +pub struct AnyView { + view: Rc>, + parent_state_type: PhantomData, +} + +impl Element for AnyView { + type State = S; + type FrameState = Box; + + fn layout( + &mut self, + _: &mut Self::State, + cx: &mut ViewContext, + ) -> Result<(LayoutId, Self::FrameState)> { + self.view.borrow_mut().layout(cx) + } + + fn paint( + &mut self, + layout: Layout, + _: &mut Self::State, + element: &mut Self::FrameState, + cx: &mut ViewContext, + ) -> Result<()> { + self.view.borrow_mut().paint(layout, element, cx) + } +} + +impl Clone for AnyView { + fn clone(&self) -> Self { + Self { + view: self.view.clone(), + parent_state_type: PhantomData, + } + } +} diff --git a/crates/gpui3/src/window.rs b/crates/gpui3/src/window.rs index 329037cb91b8e54b257af9c2b5dff1bef250a27f..ec804159e25b76e4dfa40a7eaa9f30d67be359d2 100644 --- a/crates/gpui3/src/window.rs +++ b/crates/gpui3/src/window.rs @@ -1,4 +1,6 @@ -use crate::{AvailableSpace, PlatformWindow, Point, Size, Style, TextStyle, TextStyleRefinement}; +use crate::{ + AvailableSpace, Bg, PlatformWindow, Point, Size, Style, TextStyle, TextStyleRefinement, +}; use super::{ px, taffy::LayoutId, AppContext, Bounds, Context, EntityId, Handle, Pixels, Reference, @@ -45,7 +47,7 @@ pub struct WindowContext<'a, 'b> { } impl<'a, 'w> WindowContext<'a, 'w> { - pub(crate) fn mutable(app: &'a mut AppContext, window: &'w mut Window) -> Self { + pub(crate) fn mutable(app: &'a mut AppContext, window: &'w mut Window) -> Self { Self { app: Reference::Mutable(app), window: Reference::Mutable(window),