This commit is contained in:
Nathan Sobo
2023-09-13 00:03:56 -06:00
parent faabed1df0
commit 77af33ba5d
+113 -63
View File
@@ -15,9 +15,10 @@ impl AppContext {
unimplemented!()
}
pub fn open_window<E, S>(
pub fn open_window<S, E>(
&self,
root_view: impl Fn(ViewContext<S>) -> View<S>,
state: S,
render: impl Fn(&mut S, &mut ViewContext<S>) -> View<E>,
) -> WindowHandle<S> {
unimplemented!()
}
@@ -56,7 +57,7 @@ pub struct ModelContext<'a, T> {
entity_id: EntityId,
}
impl<'a, T> ModelContext<'a, T> {
impl<'a, T: 'static> ModelContext<'a, T> {
fn mutable(app: &'a mut AppContext, entity_id: EntityId) -> Self {
Self {
app: Reference::Mutable(app),
@@ -72,13 +73,23 @@ impl<'a, T> ModelContext<'a, T> {
entity_id,
}
}
fn update<R>(&mut self, update: impl FnOnce(&mut T, &mut Self) -> R) -> R {
let mut entity = self.app.entities.remove(&self.entity_id).unwrap();
let result = update(entity.downcast_mut::<T>().unwrap(), self);
self.app.entities.insert(self.entity_id, Box::new(entity));
result
}
}
pub struct Window {
id: WindowId,
}
#[derive(Deref, DerefMut)]
pub struct WindowContext<'a, 'b> {
#[deref]
#[deref_mut]
app: Reference<'a, AppContext>,
window: Reference<'b, Window>,
}
@@ -91,19 +102,29 @@ impl<'a, 'w> WindowContext<'a, 'w> {
}
}
fn immutable(app: &'a AppContext, window: &'w Window) -> Self {
Self {
app: Reference::Immutable(app),
window: Reference::Immutable(window),
}
}
fn app_context(&mut self) -> &mut AppContext {
&mut *self.app
}
}
impl<'app, 'win> WindowContext<'app, 'win> {
impl<'a, 'w> WindowContext<'a, 'w> {
fn add_entity<T: 'static>(
&mut self,
build_entity: impl FnOnce(&mut ViewContext<'_, 'app, 'win, T>) -> T,
build_entity: impl FnOnce(&mut ViewContext<'_, '_, T>) -> T,
) -> Handle<T> {
let id = EntityId::new(&mut self.app_context().entity_count);
let mut cx = ViewContext::mutable(self, id);
let entity = build_entity(&mut cx);
let entity = build_entity(&mut ViewContext::mutable(
&mut *self.app,
&mut *self.window,
id,
));
self.app.entities.insert(id, Box::new(entity));
Handle {
id,
@@ -119,7 +140,7 @@ impl<'app, 'win> WindowContext<'app, 'win> {
let mut entity = self.app.entities.remove(&handle.id).unwrap();
let result = update(
entity.downcast_mut().unwrap(),
&mut ViewContext::mutable(self, handle.id),
&mut ViewContext::mutable(&mut *self.app, &mut *self.window, handle.id),
);
self.app.entities.insert(handle.id, entity);
result
@@ -139,26 +160,36 @@ impl<'app, 'win> WindowContext<'app, 'win> {
}
#[derive(Deref, DerefMut)]
pub struct ViewContext<'parent, 'app, 'win, T> {
pub struct ViewContext<'a, 'w, T> {
#[deref]
#[deref_mut]
window_cx: Reference<'parent, WindowContext<'app, 'win>>,
window_cx: WindowContext<'a, 'w>,
entity_type: PhantomData<T>,
entity_id: EntityId,
}
impl<'cx, 'app: 'cx, 'win: 'cx, V> ViewContext<'cx, 'app, 'win, V> {
fn mutable(window_cx: &'cx mut WindowContext<'app, 'win>, entity_id: EntityId) -> Self {
impl<'a, 'w, T: 'static> ViewContext<'a, 'w, T> {
fn update<R>(&mut self, update: impl FnOnce(&mut T, &mut Self) -> R) -> R {
let mut entity = self.window_cx.app.entities.remove(&self.entity_id).unwrap();
let result = update(entity.downcast_mut::<T>().unwrap(), self);
self.window_cx
.app
.entities
.insert(self.entity_id, Box::new(entity));
result
}
fn mutable(app: &'a mut AppContext, window: &'w mut Window, entity_id: EntityId) -> Self {
Self {
window_cx: Reference::Mutable(window_cx),
window_cx: WindowContext::mutable(app, window),
entity_id,
entity_type: PhantomData,
}
}
fn immutable(window_cx: &'cx WindowContext<'app, 'win>, entity_id: EntityId) -> Self {
fn immutable(app: &'a AppContext, window: &'w Window, entity_id: EntityId) -> Self {
Self {
window_cx: Reference::Immutable(window_cx),
window_cx: WindowContext::immutable(app, window),
entity_id,
entity_type: PhantomData,
}
@@ -192,28 +223,23 @@ impl EntityId {
}
}
pub struct Handle<T> {
id: EntityId,
entity_type: PhantomData<T>,
}
trait Context {
type EntityContext<'cx, 'app, 'win, T: 'static>;
type EntityContext<'a, 'w, T: 'static>;
fn update_entity<'a, 'app, 'win, T: 'static, R>(
&'a mut self,
fn update_entity<T: 'static, R>(
&mut self,
handle: &Handle<T>,
update: impl for<'cx> FnOnce(&mut T, &mut Self::EntityContext<'cx, 'app, 'win, T>) -> R,
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
) -> R;
}
impl Context for AppContext {
type EntityContext<'cx, 'app, 'win, T: 'static> = ModelContext<'cx, T>;
type EntityContext<'a, 'w, T: 'static> = ModelContext<'a, T>;
fn update_entity<'a, 'app, 'win, T: 'static, R>(
&'a mut self,
fn update_entity<T: 'static, R>(
&mut self,
handle: &Handle<T>,
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, 'app, 'win, T>) -> R,
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
) -> R {
let mut entity = self
.entities
@@ -227,31 +253,40 @@ impl Context for AppContext {
}
}
// impl<'app, 'win> Context for WindowContext<'app, 'win> {
// type EntityContext<'cx, 'app, 'win, T: 'static> = ModelContext<'cx, T>;
impl Context for WindowContext<'_, '_> {
type EntityContext<'a, 'w, T: 'static> = ViewContext<'a, 'w, T>;
// fn update_entity<'a, 'app, 'win, T: 'static, R>(
// &'a mut self,
// handle: &Handle<T>,
// update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, 'app, 'win, T>) -> R,
// ) -> R {
// let mut entity = self
// .entities
// .remove(&handle.id)
// .unwrap()
// .downcast::<T>()
// .unwrap();
// let result = update(&mut *entity, &mut ModelContext::mutable(self, handle.id));
// self.entities.insert(handle.id, Box::new(entity));
// result
// }
// }
fn update_entity<T: 'static, R>(
&mut self,
handle: &Handle<T>,
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
) -> R {
let mut entity = self
.app
.entities
.remove(&handle.id)
.unwrap()
.downcast::<T>()
.unwrap();
let result = update(
&mut *entity,
&mut ViewContext::mutable(&mut *self.app, &mut *self.window, handle.id),
);
self.entities.insert(handle.id, Box::new(entity));
result
}
}
pub struct Handle<T> {
id: EntityId,
entity_type: PhantomData<T>,
}
impl<T: 'static> Handle<T> {
fn update<'app, 'win, C: Context, R>(
fn update<C: Context, R>(
&self,
cx: &mut C,
update: impl FnOnce(&mut T, &mut C::EntityContext<'_, 'app, 'win, T>) -> R,
update: impl FnOnce(&mut T, &mut C::EntityContext<'_, '_, T>) -> R,
) -> R {
cx.update_entity(self, update)
}
@@ -352,41 +387,53 @@ impl<S> AnyElement<S> {
}
pub trait IntoAnyElement<S> {
fn into_any_element(self) -> AnyElement<S>;
fn into_any(self) -> AnyElement<S>;
}
impl<E: Element> IntoAnyElement<E::State> for E {
fn into_any_element(self) -> AnyElement<E::State> {
fn into_any(self) -> AnyElement<E::State> {
AnyElement(Box::new(RenderedElement::new(self)))
}
}
impl<S> IntoAnyElement<S> for AnyElement<S> {
fn into_any_element(self) -> AnyElement<S> {
fn into_any(self) -> AnyElement<S> {
self
}
}
pub struct View<S> {
render: Rc<dyn Fn(&mut WindowContext) -> AnyElement<S>>,
pub struct View<E> {
render: Rc<dyn Fn(&mut WindowContext) -> E>,
}
impl<S> View<S> {
fn render(&self, cx: &mut WindowContext) -> AnyElement<S> {
impl<E> View<E> {
fn render(&self, cx: &mut WindowContext) -> E {
(self.render)(cx)
}
}
pub fn view<ParentState, ChildState: 'static>(
state: Handle<ChildState>,
render: impl 'static + Fn(&mut ChildState, &mut ViewContext<ChildState>) -> AnyElement<ParentState>,
) -> View<ParentState> {
pub fn view<S: 'static, E: Element<State = S>>(
state: Handle<S>,
render: impl 'static + Fn(&mut S, &mut ViewContext<S>) -> E,
) -> View<E> {
View {
// render: Rc::new(move |cx| state.update(cx, |state, cx| render(state, cx))),
render: todo!(),
render: Rc::new(move |cx| state.update(cx, |state, cx| render(state, cx))),
}
}
trait ViewObject<S> {
fn render(cx: &mut WindowContext) -> AnyElement<S>;
}
impl<S: 'static, E: Element<State = S>> ViewObject<S> for View<E> {
fn render<V>(&mut self, cx: &mut WindowContext) -> AnyElement<V> {
let element = (self.render)(cx);
AnyElement(Box::new(RenderedElement::new(element)))
}
}
pub struct AnyView(Box<dyn ViewObject<S>);
pub struct Div<S>(PhantomData<S>);
impl<S: 'static> Element for Div<S> {
@@ -423,7 +470,7 @@ pub fn div<S>() -> Div<S> {
}
pub struct Workspace {
left_panel: View<Self>,
left_panel: AnyView,
}
fn workspace(
@@ -471,7 +518,10 @@ mod tests {
#[test]
fn test() {
let mut cx = AppContext::new();
// let collab_panel = cx.add_entity(|cx| CollabPanel::new(cx));
let collab_panel = cx.open_window(|cx| {
let panel = cx.add_entity(|cx| CollabPanel::new(cx));
view(panel, |panel, cx| div().into_any())
});
// let
// let mut workspace = Workspace {