Checkpoint
This commit is contained in:
+91
-152
@@ -1,95 +1,56 @@
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
use derive_more::{Deref, DerefMut};
|
||||||
use gpui2::{Layout, LayoutId, Reference, Vector2F};
|
use gpui2::{Layout, LayoutId, Reference, Vector2F};
|
||||||
use std::{any::Any, collections::HashMap, marker::PhantomData, rc::Rc};
|
use std::{any::Any, collections::HashMap, marker::PhantomData, rc::Rc};
|
||||||
|
|
||||||
pub trait Context {
|
|
||||||
type EntityContext<'a, 'b, T>;
|
|
||||||
|
|
||||||
fn add_entity<F, T>(&mut self, build_entity: F) -> Handle<T>
|
|
||||||
where
|
|
||||||
F: FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T;
|
|
||||||
|
|
||||||
fn update_entity<F, T, R>(&mut self, handle: &Handle<T>, update: F) -> R
|
|
||||||
where
|
|
||||||
F: FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
|
||||||
T: 'static;
|
|
||||||
|
|
||||||
fn update_window<F, R>(&mut self, window_id: WindowId, update: F) -> Result<R>
|
|
||||||
where
|
|
||||||
F: FnOnce(&mut WindowContext) -> R;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct AppContext {
|
pub struct AppContext {
|
||||||
entity_count: usize,
|
entity_count: usize,
|
||||||
entities: HashMap<EntityId, Box<dyn Any>>,
|
entities: HashMap<EntityId, Box<dyn Any>>,
|
||||||
|
window_count: usize,
|
||||||
windows: HashMap<WindowId, Window>,
|
windows: HashMap<WindowId, Window>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context for AppContext {
|
|
||||||
type EntityContext<'a, 'b, T> = ModelContext<'a, T>;
|
|
||||||
|
|
||||||
fn add_entity<F, T>(&mut self, build: F) -> Handle<T>
|
|
||||||
where
|
|
||||||
F: FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
|
|
||||||
{
|
|
||||||
let id = EntityId::new(&mut self.entity_count);
|
|
||||||
let entity = build(&mut ModelContext::mutable(self, id));
|
|
||||||
self.entities.insert(id, Box::new(entity));
|
|
||||||
Handle {
|
|
||||||
id,
|
|
||||||
entity_type: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_entity<F, T, R>(&mut self, handle: &Handle<T>, update: F) -> R
|
|
||||||
where
|
|
||||||
F: FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
|
||||||
T: 'static,
|
|
||||||
{
|
|
||||||
let mut entity = self.entities.remove(&handle.id).unwrap();
|
|
||||||
let result = update(
|
|
||||||
entity.downcast_mut().unwrap(),
|
|
||||||
&mut ModelContext::mutable(self, handle.id),
|
|
||||||
);
|
|
||||||
self.entities.insert(handle.id, entity);
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_window<F, R>(&mut self, window_id: WindowId, update: F) -> Result<R>
|
|
||||||
where
|
|
||||||
F: FnOnce(&mut WindowContext<'_, '_>) -> R,
|
|
||||||
{
|
|
||||||
let mut window = self
|
|
||||||
.windows
|
|
||||||
.remove(&window_id)
|
|
||||||
.ok_or_else(|| anyhow!("window closed"))?;
|
|
||||||
let result = update(&mut WindowContext::mutable(self, &mut window));
|
|
||||||
self.windows.insert(window_id, window);
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AppContext {
|
impl AppContext {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_window<E, S>(&self, root_element: E, state: S) -> WindowHandle<S> {
|
pub fn open_window<E, S>(
|
||||||
|
&self,
|
||||||
|
root_view: impl Fn(ViewContext<S>) -> View<S>,
|
||||||
|
) -> WindowHandle<S> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_entity<T, F>(&mut self, entity: F) -> Handle<T>
|
fn add_entity<T: 'static>(
|
||||||
where
|
&mut self,
|
||||||
F: FnOnce(&mut ModelContext<T>) -> T,
|
build_entity: impl FnOnce(&mut ModelContext<T>) -> T,
|
||||||
{
|
) -> Handle<T> {
|
||||||
let id = EntityId::new(&mut self.entity_count);
|
let id = EntityId::new(&mut self.entity_count);
|
||||||
|
let entity = build_entity(&mut ModelContext::mutable(self, id));
|
||||||
|
self.entities.insert(id, Box::new(entity));
|
||||||
Handle {
|
Handle {
|
||||||
id,
|
id,
|
||||||
entity_type: PhantomData,
|
entity_type: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_entity<T: 'static, R>(
|
||||||
|
&mut self,
|
||||||
|
handle: &Handle<T>,
|
||||||
|
update: impl FnOnce(&mut T, &mut ModelContext<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_window<R>(
|
fn update_window<R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
window_id: WindowId,
|
window_id: WindowId,
|
||||||
@@ -99,9 +60,7 @@ impl AppContext {
|
|||||||
.windows
|
.windows
|
||||||
.remove(&window_id)
|
.remove(&window_id)
|
||||||
.ok_or_else(|| anyhow!("window not found"))?;
|
.ok_or_else(|| anyhow!("window not found"))?;
|
||||||
|
let result = update(&mut WindowContext::mutable(self, &mut window));
|
||||||
let mut cx = WindowContext::mutable(self, &mut window);
|
|
||||||
let result = update(&mut cx);
|
|
||||||
self.windows.insert(window_id, window);
|
self.windows.insert(window_id, window);
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
@@ -114,7 +73,7 @@ pub struct ModelContext<'a, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> ModelContext<'a, T> {
|
impl<'a, T> ModelContext<'a, T> {
|
||||||
fn mutable(app: &mut AppContext, entity_id: EntityId) -> Self {
|
fn mutable(app: &'a mut AppContext, entity_id: EntityId) -> Self {
|
||||||
Self {
|
Self {
|
||||||
app: Reference::Mutable(app),
|
app: Reference::Mutable(app),
|
||||||
entity_type: PhantomData,
|
entity_type: PhantomData,
|
||||||
@@ -122,7 +81,7 @@ impl<'a, T> ModelContext<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn immutable(app: &AppContext, entity_id: EntityId) -> Self {
|
fn immutable(app: &'a AppContext, entity_id: EntityId) -> Self {
|
||||||
Self {
|
Self {
|
||||||
app: Reference::Immutable(app),
|
app: Reference::Immutable(app),
|
||||||
entity_type: PhantomData,
|
entity_type: PhantomData,
|
||||||
@@ -140,8 +99,8 @@ pub struct WindowContext<'a, 'b> {
|
|||||||
window: Reference<'b, Window>,
|
window: Reference<'b, Window>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> WindowContext<'a, 'b> {
|
impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
fn mutable(app: &mut AppContext, window: &mut Window) -> Self {
|
fn mutable(app: &'a mut AppContext, window: &'w mut Window) -> Self {
|
||||||
Self {
|
Self {
|
||||||
app: Reference::Mutable(app),
|
app: Reference::Mutable(app),
|
||||||
window: Reference::Mutable(window),
|
window: Reference::Mutable(window),
|
||||||
@@ -153,15 +112,13 @@ impl<'a, 'b> WindowContext<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> Context for WindowContext<'a, 'b> {
|
impl<'app, 'win> WindowContext<'app, 'win> {
|
||||||
type EntityContext<'c, 'd, T> = ViewContext<'c, 'd, T>;
|
fn add_entity<T: 'static>(
|
||||||
|
&mut self,
|
||||||
fn add_entity<F, T>(&mut self, build_entity: F) -> Handle<T>
|
build_entity: impl FnOnce(&mut ViewContext<'app, 'win, '_, T>) -> T,
|
||||||
where
|
) -> Handle<T> {
|
||||||
F: FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
|
|
||||||
{
|
|
||||||
let id = EntityId::new(&mut self.app_context().entity_count);
|
let id = EntityId::new(&mut self.app_context().entity_count);
|
||||||
let mut cx = ViewContext::mutable(&mut self.app_context(), &mut self.window, id);
|
let mut cx = ViewContext::mutable(self, id);
|
||||||
let entity = build_entity(&mut cx);
|
let entity = build_entity(&mut cx);
|
||||||
self.app.entities.insert(id, Box::new(entity));
|
self.app.entities.insert(id, Box::new(entity));
|
||||||
Handle {
|
Handle {
|
||||||
@@ -170,24 +127,25 @@ impl<'a, 'b> Context for WindowContext<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_entity<F, T, R>(&mut self, handle: &Handle<T>, update: F) -> R
|
fn update_entity<T: 'static, R>(
|
||||||
where
|
&mut self,
|
||||||
F: FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
handle: &Handle<T>,
|
||||||
T: 'static,
|
update: impl FnOnce(&mut T, &mut ViewContext<T>) -> R,
|
||||||
{
|
) -> R {
|
||||||
let mut entity = self.app.entities.remove(&handle.id).unwrap();
|
let mut entity = self.app.entities.remove(&handle.id).unwrap();
|
||||||
let result = update(
|
let result = update(
|
||||||
entity.downcast_mut().unwrap(),
|
entity.downcast_mut().unwrap(),
|
||||||
&mut ViewContext::mutable(&mut self.app, &mut self.window, handle.id),
|
&mut ViewContext::mutable(self, handle.id),
|
||||||
);
|
);
|
||||||
self.app.entities.insert(handle.id, entity);
|
self.app.entities.insert(handle.id, entity);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_window<F, R>(&mut self, window_id: WindowId, update: F) -> Result<R>
|
fn update_window<R>(
|
||||||
where
|
&mut self,
|
||||||
F: FnOnce(&mut WindowContext) -> R,
|
window_id: WindowId,
|
||||||
{
|
update: impl FnOnce(&mut WindowContext) -> R,
|
||||||
|
) -> Result<R> {
|
||||||
if window_id == self.window.id {
|
if window_id == self.window.id {
|
||||||
Ok(update(self))
|
Ok(update(self))
|
||||||
} else {
|
} else {
|
||||||
@@ -196,77 +154,48 @@ impl<'a, 'b> Context for WindowContext<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ViewContext<'a, 'b, T> {
|
#[derive(Deref, DerefMut)]
|
||||||
app: Reference<'a, AppContext>,
|
pub struct ViewContext<'a, 'b, 'c, T> {
|
||||||
window: Reference<'b, Window>,
|
#[deref]
|
||||||
|
#[deref_mut]
|
||||||
|
window_cx: Reference<'c, WindowContext<'a, 'b>>,
|
||||||
entity_type: PhantomData<T>,
|
entity_type: PhantomData<T>,
|
||||||
entity_id: EntityId,
|
entity_id: EntityId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, V> ViewContext<'a, 'b, V> {
|
impl<'a, 'b, 'c, V> ViewContext<'a, 'b, 'c, V> {
|
||||||
fn mutable(app: &'a mut AppContext, window: &'b mut Window, entity_id: EntityId) -> Self {
|
fn mutable(window_cx: &'c mut WindowContext<'a, 'b>, entity_id: EntityId) -> Self {
|
||||||
Self {
|
Self {
|
||||||
app: Reference::Mutable(app),
|
window_cx: Reference::Mutable(window_cx),
|
||||||
window: Reference::Mutable(window),
|
|
||||||
entity_type: PhantomData,
|
|
||||||
entity_id,
|
entity_id,
|
||||||
|
entity_type: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn immutable(app: &'a AppContext, window: &'b Window, entity_id: EntityId) -> Self {
|
fn immutable(window_cx: &'c WindowContext<'a, 'b>, entity_id: EntityId) -> Self {
|
||||||
Self {
|
Self {
|
||||||
app: Reference::Immutable(app),
|
window_cx: Reference::Immutable(window_cx),
|
||||||
window: Reference::Immutable(window),
|
|
||||||
entity_type: PhantomData,
|
|
||||||
entity_id,
|
entity_id,
|
||||||
|
entity_type: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn window_context(&self) -> WindowContext {
|
|
||||||
WindowContext {
|
|
||||||
app: Reference::Immutable(&*self.app),
|
|
||||||
window: Reference::Immutable(&*self.window),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn window_context_mut(&mut self) -> WindowContext {
|
|
||||||
WindowContext {
|
|
||||||
app: Reference::Mutable(&mut *self.app),
|
|
||||||
window: Reference::Mutable(&mut *self.window),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'b, V> Context for ViewContext<'a, 'b, V> {
|
|
||||||
type EntityContext<'c, 'd, T> = ViewContext<'c, 'd, T>;
|
|
||||||
|
|
||||||
fn add_entity<F, T>(&mut self, build_entity: F) -> Handle<T>
|
|
||||||
where
|
|
||||||
F: FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
|
|
||||||
{
|
|
||||||
self.window_context_mut().add_entity(build_entity)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_entity<F, T, R>(&mut self, handle: &Handle<T>, update: F) -> R
|
|
||||||
where
|
|
||||||
F: FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
|
||||||
T: 'static,
|
|
||||||
{
|
|
||||||
self.window_context_mut().update_entity(handle, update)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_window<F, R>(&mut self, window_id: WindowId, update: F) -> Result<R>
|
|
||||||
where
|
|
||||||
F: FnOnce(&mut WindowContext<'_, '_>) -> R,
|
|
||||||
{
|
|
||||||
self.window_context_mut().update_window(window_id, update)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
|
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
pub struct WindowId(usize);
|
pub struct WindowId(usize);
|
||||||
|
|
||||||
pub struct WindowHandle<S>(PhantomData<S>);
|
impl WindowId {
|
||||||
|
fn new(window_count: &mut usize) -> Self {
|
||||||
|
let id = *window_count;
|
||||||
|
*window_count += 1;
|
||||||
|
Self(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WindowHandle<S> {
|
||||||
|
id: WindowId,
|
||||||
|
state_type: PhantomData<S>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
|
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
pub struct EntityId(usize);
|
pub struct EntityId(usize);
|
||||||
@@ -284,11 +213,21 @@ pub struct Handle<T> {
|
|||||||
entity_type: PhantomData<T>,
|
entity_type: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: 'static> Handle<T> {
|
trait Context {
|
||||||
fn update<'a, C: Context, R>(
|
type EntityContext<T>;
|
||||||
|
|
||||||
|
fn update_entity<T, R>(
|
||||||
|
&mut self,
|
||||||
|
handle: &Handle<T>,
|
||||||
|
update: impl FnOnce(&mut T, Self::EntityContext<T>) -> R,
|
||||||
|
) -> R;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Handle<T> {
|
||||||
|
fn update<C: Context, R>(
|
||||||
&self,
|
&self,
|
||||||
cx: &'a mut C,
|
cx: &mut C,
|
||||||
update: impl FnOnce(&mut T, &mut C::EntityContext<'_, '_, T>) -> R,
|
update: impl FnOnce(&mut T, C::EntityContext<T>) -> R,
|
||||||
) -> R {
|
) -> R {
|
||||||
cx.update_entity(self, update)
|
cx.update_entity(self, update)
|
||||||
}
|
}
|
||||||
@@ -419,7 +358,7 @@ pub fn view<ParentState, ChildState: 'static>(
|
|||||||
render: impl 'static + Fn(&mut ChildState, &mut ViewContext<ChildState>) -> AnyElement<ParentState>,
|
render: impl 'static + Fn(&mut ChildState, &mut ViewContext<ChildState>) -> AnyElement<ParentState>,
|
||||||
) -> View<ParentState> {
|
) -> View<ParentState> {
|
||||||
View {
|
View {
|
||||||
render: Rc::new(move |cx| state.update(cx, |state, cx| render(state, cx))),
|
render: todo!(), // Rc::new(move |cx| state.update(cx, |state, cx| render(state, cx))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,7 +405,7 @@ fn workspace(
|
|||||||
state: &mut Workspace,
|
state: &mut Workspace,
|
||||||
cx: &mut ViewContext<Workspace>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
) -> impl Element<State = Workspace> {
|
) -> impl Element<State = Workspace> {
|
||||||
div().child(state.left_panel.render(&mut cx))
|
div().child(state.left_panel.render(cx))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CollabPanel {
|
pub struct CollabPanel {
|
||||||
@@ -507,7 +446,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
let mut cx = AppContext::new();
|
let mut cx = AppContext::new();
|
||||||
let collab_panel = cx.add_entity(|cx| CollabPanel::new(cx));
|
// let collab_panel = cx.add_entity(|cx| CollabPanel::new(cx));
|
||||||
|
|
||||||
// let
|
// let
|
||||||
// let mut workspace = Workspace {
|
// let mut workspace = Workspace {
|
||||||
|
|||||||
Reference in New Issue
Block a user