This commit is contained in:
Nathan Sobo 2024-12-19 11:00:32 -07:00
parent 2583f8ecb0
commit acaa720c09
6 changed files with 74 additions and 59 deletions

View file

@ -413,16 +413,17 @@ impl AppContext {
self.pending_effects.push_back(Effect::Refresh);
}
pub(crate) fn update<R>(&mut self, update: impl FnOnce(&mut Self) -> R) -> R {
self.pending_updates += 1;
let result = update(self);
if !self.flushing_effects && self.pending_updates == 1 {
self.flushing_effects = true;
self.flush_effects();
self.flushing_effects = false;
}
self.pending_updates -= 1;
result
pub(crate) fn update<'a, R>(&'a mut self, update: impl FnOnce(&'a mut Self) -> R) -> R {
todo!()
// self.pending_updates += 1;
// let result = update(self);
// if !self.flushing_effects && self.pending_updates == 1 {
// self.flushing_effects = true;
// self.flush_effects();
// self.flushing_effects = false;
// }
// self.pending_updates -= 1;
// result
}
/// Arrange a callback to be invoked when the given model or view calls `notify` on its respective context.
@ -1413,11 +1414,23 @@ impl AppContext {
pub fn get_name(&self) -> &'static str {
self.name.as_ref().unwrap()
}
fn insert_model2<'a, T: 'static>(
&'a mut self,
reservation: Reservation<T>,
build_model: impl FnOnce(&mut ModelContext<'a, 'b, T>) -> T,
) -> Model<T> {
self.update(|cx| {
let slot = reservation.0;
let entity = build_model(&mut ModelContext::new(cx, &slot));
cx.entities.insert(slot, entity)
})
}
}
impl Context for AppContext {
type Result<T> = T;
type EntityContext<'a, 'b, T: 'static> = ModelContext<'a, T>;
type EntityContext<'a, 'b, T: 'static> = ModelContext<'a, 'b, T>;
/// Build an entity that is owned by the application. The given function will be invoked with
/// a `ModelContext` and must return an object representing the entity. A `Model` handle will be returned,

View file

@ -20,7 +20,7 @@ pub struct AsyncAppContext {
impl Context for AsyncAppContext {
type Result<T> = Result<T>;
type EntityContext<'a, 'b, T: 'static> = ModelContext<'a, T>;
type EntityContext<'a, 'b, T: 'static> = ModelContext<'a, 'b, T>;
fn new_model<T: 'static>(
&mut self,

View file

@ -13,15 +13,15 @@ use std::{
/// The app context, with specialized behavior for the given model.
#[derive(Deref, DerefMut)]
pub struct ModelContext<'a, T> {
pub struct ModelContext<'a, 'b, T> {
#[deref]
#[deref_mut]
pub(crate) app: &'a mut AppContext,
pub(crate) entity: &'a Model<T>,
pub(crate) entity: &'b Model<T>,
}
impl<'a, T: 'static> ModelContext<'a, T> {
pub(crate) fn new(app: &'a mut AppContext, model_state: &'a Model<T>) -> Self {
impl<'a, 'b, T: 'static> ModelContext<'a, 'b, T> {
pub(crate) fn new(app: &'a mut AppContext, model_state: &'b Model<T>) -> Self {
Self {
app,
entity: model_state,
@ -48,7 +48,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
pub fn observe<W, E>(
&mut self,
entity: &E,
mut on_notify: impl FnMut(&mut T, E, &mut ModelContext<'_, T>) + 'static,
mut on_notify: impl FnMut(&mut T, E, &mut ModelContext<'_, '_, T>) + 'static,
) -> Subscription
where
T: 'static,
@ -70,7 +70,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
pub fn subscribe<T2, E, Evt>(
&mut self,
entity: &E,
mut on_event: impl FnMut(&mut T, E, &Evt, &mut ModelContext<'_, T>) + 'static,
mut on_event: impl FnMut(&mut T, E, &Evt, &mut ModelContext<'_, '_, T>) + 'static,
) -> Subscription
where
T: 'static,
@ -112,7 +112,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
pub fn observe_release<T2, E>(
&self,
entity: &E,
on_release: impl FnOnce(&mut T, &mut T2, &mut ModelContext<'_, T>) + 'static,
on_release: impl FnOnce(&mut T, &mut T2, &mut ModelContext<'_, '_, T>) + 'static,
) -> Subscription
where
T: Any,
@ -137,7 +137,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
/// Register a callback to for updates to the given global
pub fn observe_global<G: 'static>(
&mut self,
mut f: impl FnMut(&mut T, &mut ModelContext<'_, T>) + 'static,
mut f: impl FnMut(&mut T, &mut ModelContext<'_, '_, T>) + 'static,
) -> Subscription
where
T: 'static,
@ -210,7 +210,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
}
}
impl<'a, T> ModelContext<'a, T> {
impl<'a, 'b, T> ModelContext<'a, 'b, T> {
/// Emit an event of the specified type, which can be handled by other entities that have subscribed via `subscribe` methods on their respective contexts.
pub fn emit<Evt>(&mut self, event: Evt)
where
@ -225,13 +225,13 @@ impl<'a, T> ModelContext<'a, T> {
}
}
impl<'a, T> Context for ModelContext<'a, T> {
impl<'a, 'b, T> Context for ModelContext<'a, 'b, T> {
type Result<U> = U;
type EntityContext<'b, 'c, U: 'static> = ModelContext<'b, U>;
type EntityContext<'c, 'd, U: 'static> = ModelContext<'c, 'd, U>;
fn new_model<U: 'static>(
&mut self,
build_model: impl FnOnce(&mut ModelContext<'_, U>) -> U,
build_model: impl FnOnce(&mut Self::EntityContext<'_, '_, U>) -> U,
) -> Model<U> {
self.app.new_model(build_model)
}
@ -243,7 +243,7 @@ impl<'a, T> Context for ModelContext<'a, T> {
fn insert_model<U: 'static>(
&mut self,
reservation: Reservation<U>,
build_model: impl FnOnce(&mut ModelContext<'_, U>) -> U,
build_model: impl FnOnce(&mut ModelContext<'_, '_, U>) -> U,
) -> Self::Result<Model<U>> {
self.app.insert_model(reservation, build_model)
}
@ -251,7 +251,7 @@ impl<'a, T> Context for ModelContext<'a, T> {
fn update_model<U: 'static, R>(
&mut self,
handle: &Model<U>,
update: impl FnOnce(&mut U, &mut ModelContext<'_, U>) -> R,
update: impl FnOnce(&mut U, &mut ModelContext<'_, '_, U>) -> R,
) -> R {
self.app.update_model(handle, update)
}
@ -286,13 +286,13 @@ impl<'a, T> Context for ModelContext<'a, T> {
}
}
impl<T> Borrow<AppContext> for ModelContext<'_, T> {
impl<T> Borrow<AppContext> for ModelContext<'_, '_, T> {
fn borrow(&self) -> &AppContext {
self.app
}
}
impl<T> BorrowMut<AppContext> for ModelContext<'_, T> {
impl<T> BorrowMut<AppContext> for ModelContext<'_, '_, T> {
fn borrow_mut(&mut self) -> &mut AppContext {
self.app
}

View file

@ -31,7 +31,7 @@ pub struct TestAppContext {
impl Context for TestAppContext {
type Result<T> = T;
type EntityContext<'a, 'b, T: 'static> = ModelContext<'a, T>;
type EntityContext<'a, 'b, T: 'static> = ModelContext<'a, 'b, T>;
fn new_model<T: 'static>(
&mut self,

View file

@ -165,12 +165,12 @@ pub trait Context {
/// Defines the context type used when updating an entity within this context.
/// This associated type specifies the appropriate context for entity updates,
/// allowing for context-specific operations and ensuring type safety.
type EntityContext<'a, 'b, T: 'static>;
type EntityContext<'a, 'b, 'c, T: 'static>;
/// Create a new model in the app context.
fn new_model<T: 'static>(
&mut self,
build_model: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
build_model: impl FnOnce(&mut Self::EntityContext<'_, '_, '_, T>) -> T,
) -> Self::Result<Model<T>>;
/// Reserve a slot for a model to be inserted later.
@ -183,14 +183,14 @@ pub trait Context {
fn insert_model<T: 'static>(
&mut self,
reservation: Reservation<T>,
build_model: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
build_model: impl FnOnce(&mut Self::EntityContext<'_, '_, '_, T>) -> T,
) -> Self::Result<Model<T>>;
/// Update a model in the app context.
fn update_model<T, R>(
&mut self,
handle: &Model<T>,
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, '_, T>) -> R,
) -> Self::Result<R>
where
T: 'static;

View file

@ -6615,11 +6615,13 @@ impl Context for WindowContext<'_> {
reservation: crate::Reservation<T>,
build_model: impl FnOnce(&mut ViewContext<'_, '_, T>) -> T,
) -> Self::Result<Model<T>> {
self.app.update(|cx| {
let slot = reservation.0;
let entity = build_model(&mut ViewContext::new(cx, &slot));
cx.entities.insert(slot, entity)
})
self.app
.insert_model(reservation, |cx: &mut ModelContext<'_, T>| {
// let window = &mut self.window;
ViewContext::new(cx, &mut self.window);
// build_model(&mut cx)
todo!()
})
}
fn update_model<T: 'static, R>(
@ -6686,7 +6688,7 @@ impl Context for WindowContext<'_> {
impl VisualContext for WindowContext<'_> {
fn new_view<V>(
&mut self,
build_view_state: impl FnOnce(&mut ViewContext<'_, '_, V>) -> V,
build_view_state: impl FnOnce(&mut ViewContext<'_, '_, '_, V>) -> V,
) -> Self::Result<Model<V>>
where
V: 'static + Render,
@ -6723,7 +6725,7 @@ impl VisualContext for WindowContext<'_> {
fn replace_root_view<V>(
&mut self,
build_view: impl FnOnce(&mut ViewContext<'_, '_, V>) -> V,
build_view: impl FnOnce(&mut ViewContext<'_, '_, '_, V>) -> V,
) -> Self::Result<Model<V>>
where
V: 'static + Render,
@ -6815,37 +6817,37 @@ impl<T> BorrowWindow for T where T: BorrowMut<AppContext> + BorrowMut<Window> {}
/// Allows you to interact with focus, emit events, etc.
/// ViewContext also derefs to [`WindowContext`], giving you access to all of its methods as well.
/// When you call [`View::update`], you're passed a `&mut V` and an `&mut ViewContext<V>`.
pub struct ViewContext<'a, 'b, V> {
cx: &'a mut ModelContext<'a, V>,
window: &'b mut Window,
pub struct ViewContext<'a, 'b, 'c, V> {
cx: &'a mut ModelContext<'a, 'b, V>,
window: &'c mut Window,
}
impl<V> Borrow<AppContext> for ViewContext<'_, '_, V> {
impl<V> Borrow<AppContext> for ViewContext<'_, '_, '_, V> {
fn borrow(&self) -> &AppContext {
&*self.cx
}
}
impl<V> BorrowMut<AppContext> for ViewContext<'_, '_, V> {
impl<V> BorrowMut<AppContext> for ViewContext<'_, '_, '_, V> {
fn borrow_mut(&mut self) -> &mut AppContext {
&mut *self.cx
}
}
impl<V> Borrow<Window> for ViewContext<'_, '_, V> {
impl<V> Borrow<Window> for ViewContext<'_, '_, '_, V> {
fn borrow(&self) -> &Window {
&*self.window
}
}
impl<V> BorrowMut<Window> for ViewContext<'_, '_, V> {
impl<V> BorrowMut<Window> for ViewContext<'_, '_, '_, V> {
fn borrow_mut(&mut self) -> &mut Window {
&mut *self.window
}
}
impl<'a, 'b, V: 'static> ViewContext<'a, 'b, V> {
pub(crate) fn new(cx: &'a mut ModelContext<'a, V>, window: &'b mut Window) -> Self {
impl<'a, 'b, 'c, V: 'static> ViewContext<'a, 'b, 'c, V> {
pub(crate) fn new(cx: &'a mut ModelContext<'a, 'b, V>, window: &'c mut Window) -> Self {
Self { cx, window }
}
@ -6893,7 +6895,7 @@ impl<'a, 'b, V: 'static> ViewContext<'a, 'b, V> {
pub fn observe<V2, E>(
&mut self,
entity: &E,
mut on_notify: impl FnMut(&mut V, E, &mut ViewContext<'_, '_, V>) + 'static,
mut on_notify: impl FnMut(&mut V, E, &mut ViewContext<'_, '_, '_, V>) + 'static,
) -> Subscription
where
V2: 'static,
@ -6927,7 +6929,7 @@ impl<'a, 'b, V: 'static> ViewContext<'a, 'b, V> {
pub fn subscribe<V2, E, Evt>(
&mut self,
entity: &E,
mut on_event: impl FnMut(&mut V, E, &Evt, &mut ViewContext<'_, '_, V>) + 'static,
mut on_event: impl FnMut(&mut V, E, &Evt, &mut ViewContext<'_, '_, '_, V>) + 'static,
) -> Subscription
where
V2: EventEmitter<Evt>,
@ -6983,7 +6985,7 @@ impl<'a, 'b, V: 'static> ViewContext<'a, 'b, V> {
pub fn observe_release<V2, E>(
&self,
entity: &E,
mut on_release: impl FnMut(&mut V, &mut V2, &mut ViewContext<'_, '_, V>) + 'static,
mut on_release: impl FnMut(&mut V, &mut V2, &mut ViewContext<'_, '_, '_, V>) + 'static,
) -> Subscription
where
V: 'static,
@ -7232,7 +7234,7 @@ impl<'a, 'b, V: 'static> ViewContext<'a, 'b, V> {
/// Register a callback to be invoked when the given global state changes.
pub fn observe_global<G: Global>(
&mut self,
mut f: impl FnMut(&mut V, &mut ViewContext<'_, '_, V>) + 'static,
mut f: impl FnMut(&mut V, &mut ViewContext<'_, '_, '_, V>) + 'static,
) -> Subscription {
let window_handle = self.window.handle;
let view = self.view().downgrade();
@ -7305,7 +7307,7 @@ impl<'a, 'b, V: 'static> ViewContext<'a, 'b, V> {
}
}
impl<V> Context for ViewContext<'_, '_, V> {
impl<V> Context for ViewContext<'_, '_, '_, V> {
type Result<U> = U;
type EntityContext<'a, 'b, T: 'static> = ViewContext<'a, T>;
@ -7366,7 +7368,7 @@ impl<V> Context for ViewContext<'_, '_, V> {
}
}
impl<V: 'static> VisualContext for ViewContext<'_, '_, V> {
impl<V: 'static> VisualContext for ViewContext<'_, '_, '_, V> {
fn new_view<W: Render + 'static>(
&mut self,
build_view_state: impl FnOnce(&mut ViewContext<'_, '_, W>) -> W,
@ -7401,15 +7403,15 @@ impl<V: 'static> VisualContext for ViewContext<'_, '_, V> {
}
}
impl<'a, V> std::ops::Deref for ViewContext<'a, '_, V> {
type Target = ModelContext<'a, V>;
impl<'a, 'b, V> std::ops::Deref for ViewContext<'a, 'b, '_, V> {
type Target = ModelContext<'a, 'b, V>;
fn deref(&self) -> &Self::Target {
&self.cx
}
}
impl<'a, V> std::ops::DerefMut for ViewContext<'a, '_, V> {
impl<V> std::ops::DerefMut for ViewContext<'_, '_, '_, V> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.cx
}
@ -7477,7 +7479,7 @@ impl<V: 'static + Render> WindowHandle<V> {
pub fn update<C, R>(
&self,
cx: &mut C,
update: impl FnOnce(&mut V, &mut ViewContext<'_, '_, V>) -> R,
update: impl FnOnce(&mut V, &mut ViewContext<'_, '_, '_, V>) -> R,
) -> Result<R>
where
C: Context,