Get collab2 green

This commit is contained in:
Mikayla 2023-11-03 18:01:06 -07:00
parent c529343ba1
commit e1525e2b47
No known key found for this signature in database
265 changed files with 64477 additions and 40 deletions

View file

@ -16,8 +16,8 @@ pub use test_context::*;
use crate::{
current_platform, image_cache::ImageCache, Action, AnyBox, AnyView, AnyWindowHandle,
AppMetadata, AssetSource, BackgroundExecutor, ClipboardItem, Context, DispatchPhase, DisplayId,
Entity, FocusEvent, FocusHandle, FocusId, ForegroundExecutor, KeyBinding, Keymap, LayoutId,
PathPromptOptions, Pixels, Platform, PlatformDisplay, Point, Render, SharedString,
Entity, EventEmitter, FocusEvent, FocusHandle, FocusId, ForegroundExecutor, KeyBinding, Keymap,
LayoutId, PathPromptOptions, Pixels, Platform, PlatformDisplay, Point, Render, SharedString,
SubscriberSet, Subscription, SvgRenderer, Task, TextStyle, TextStyleRefinement, TextSystem,
View, Window, WindowContext, WindowHandle, WindowId,
};
@ -48,15 +48,19 @@ pub struct AppCell {
impl AppCell {
#[track_caller]
pub fn borrow(&self) -> AppRef {
let thread_id = std::thread::current().id();
eprintln!("borrowed {thread_id:?}");
if let Some(_) = option_env!("TRACK_THREAD_BORROWS") {
let thread_id = std::thread::current().id();
eprintln!("borrowed {thread_id:?}");
}
AppRef(self.app.borrow())
}
#[track_caller]
pub fn borrow_mut(&self) -> AppRefMut {
let thread_id = std::thread::current().id();
eprintln!("borrowed {thread_id:?}");
if let Some(_) = option_env!("TRACK_THREAD_BORROWS") {
let thread_id = std::thread::current().id();
eprintln!("borrowed {thread_id:?}");
}
AppRefMut(self.app.borrow_mut())
}
}
@ -292,6 +296,83 @@ impl AppContext {
result
}
pub fn observe<W, E>(
&mut self,
entity: &E,
mut on_notify: impl FnMut(E, &mut AppContext) + 'static,
) -> Subscription
where
W: 'static,
E: Entity<W>,
{
self.observe_internal(entity, move |e, cx| {
on_notify(e, cx);
true
})
}
pub fn observe_internal<W, E>(
&mut self,
entity: &E,
mut on_notify: impl FnMut(E, &mut AppContext) -> bool + 'static,
) -> Subscription
where
W: 'static,
E: Entity<W>,
{
let entity_id = entity.entity_id();
let handle = entity.downgrade();
self.observers.insert(
entity_id,
Box::new(move |cx| {
if let Some(handle) = E::upgrade_from(&handle) {
on_notify(handle, cx)
} else {
false
}
}),
)
}
pub fn subscribe<T, E>(
&mut self,
entity: &E,
mut on_event: impl FnMut(E, &T::Event, &mut AppContext) + 'static,
) -> Subscription
where
T: 'static + EventEmitter,
E: Entity<T>,
{
self.subscribe_internal(entity, move |entity, event, cx| {
on_event(entity, event, cx);
true
})
}
pub(crate) fn subscribe_internal<T, E>(
&mut self,
entity: &E,
mut on_event: impl FnMut(E, &T::Event, &mut AppContext) -> bool + 'static,
) -> Subscription
where
T: 'static + EventEmitter,
E: Entity<T>,
{
let entity_id = entity.entity_id();
let entity = entity.downgrade();
self.event_listeners.insert(
entity_id,
Box::new(move |event, cx| {
let event: &T::Event = event.downcast_ref().expect("invalid event type");
if let Some(handle) = E::upgrade_from(&entity) {
on_event(handle, event, cx)
} else {
false
}
}),
)
}
pub fn windows(&self) -> Vec<AnyWindowHandle> {
self.windows
.values()
@ -670,6 +751,23 @@ impl AppContext {
self.globals_by_type.insert(global_type, Box::new(global));
}
pub fn clear_globals(&mut self) {
//todo!(notify globals?)
self.globals_by_type.drain();
}
/// Set the value of the global of the given type.
pub fn remove_global<G: Any>(&mut self) -> G {
let global_type = TypeId::of::<G>();
//todo!(notify globals?)
*self
.globals_by_type
.remove(&global_type)
.unwrap_or_else(|| panic!("no global added for {}", std::any::type_name::<G>()))
.downcast()
.unwrap()
}
/// Update the global of the given type with a closure. Unlike `global_mut`, this method provides
/// your closure with mutable access to the `AppContext` and the global simultaneously.
pub fn update_global<G: 'static, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R {
@ -841,6 +939,18 @@ impl Context for AppContext {
Ok(result)
})
}
fn read_model<T, R>(
&self,
handle: &Model<T>,
read: impl FnOnce(&T, &AppContext) -> R,
) -> Self::Result<R>
where
T: 'static,
{
let entity = self.entities.read(handle);
read(entity, self)
}
}
/// These effects are processed at the end of each application update cycle.

View file

@ -45,6 +45,19 @@ impl Context for AsyncAppContext {
Ok(app.update_model(handle, update))
}
fn read_model<T, R>(
&self,
handle: &Model<T>,
callback: impl FnOnce(&T, &AppContext) -> R,
) -> Self::Result<R>
where
T: 'static,
{
let app = self.app.upgrade().context("app was released")?;
let lock = app.borrow();
Ok(lock.read_model(handle, callback))
}
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
where
F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
@ -226,6 +239,17 @@ impl Context for AsyncWindowContext {
{
self.app.update_window(window, update)
}
fn read_model<T, R>(
&self,
handle: &Model<T>,
read: impl FnOnce(&T, &AppContext) -> R,
) -> Self::Result<R>
where
T: 'static,
{
self.app.read_model(handle, read)
}
}
impl VisualContext for AsyncWindowContext {

View file

@ -325,6 +325,14 @@ impl<T: 'static> Model<T> {
cx.entities.read(self)
}
pub fn read_with<'a, R, C: Context>(
&self,
cx: &'a C,
f: impl FnOnce(&T, &AppContext) -> R,
) -> C::Result<R> {
cx.read_model(self, f)
}
/// Update the entity referenced by this model with the given function.
///
/// The update function receives a context appropriate for its environment.

View file

@ -49,19 +49,14 @@ impl<'a, T: 'static> ModelContext<'a, T> {
E: Entity<W>,
{
let this = self.weak_model();
let entity_id = entity.entity_id();
let handle = entity.downgrade();
self.app.observers.insert(
entity_id,
Box::new(move |cx| {
if let Some((this, handle)) = this.upgrade().zip(E::upgrade_from(&handle)) {
this.update(cx, |this, cx| on_notify(this, handle, cx));
true
} else {
false
}
}),
)
self.app.observe_internal(entity, move |e, cx| {
if let Some(this) = this.upgrade() {
this.update(cx, |this, cx| on_notify(this, e, cx));
true
} else {
false
}
})
}
pub fn subscribe<T2, E>(
@ -75,20 +70,14 @@ impl<'a, T: 'static> ModelContext<'a, T> {
E: Entity<T2>,
{
let this = self.weak_model();
let entity_id = entity.entity_id();
let entity = entity.downgrade();
self.app.event_listeners.insert(
entity_id,
Box::new(move |event, cx| {
let event: &T2::Event = event.downcast_ref().expect("invalid event type");
if let Some((this, handle)) = this.upgrade().zip(E::upgrade_from(&entity)) {
this.update(cx, |this, cx| on_event(this, handle, event, cx));
true
} else {
false
}
}),
)
self.app.subscribe_internal(entity, move |e, event, cx| {
if let Some(this) = this.upgrade() {
this.update(cx, |this, cx| on_event(this, e, event, cx));
true
} else {
false
}
})
}
pub fn on_release(
@ -236,6 +225,17 @@ impl<'a, T> Context for ModelContext<'a, T> {
{
self.app.update_window(window, update)
}
fn read_model<U, R>(
&self,
handle: &Model<U>,
read: impl FnOnce(&U, &AppContext) -> R,
) -> Self::Result<R>
where
U: 'static,
{
self.app.read_model(handle, read)
}
}
impl<T> Borrow<AppContext> for ModelContext<'_, T> {

View file

@ -1,7 +1,7 @@
use crate::{
AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext, BackgroundExecutor, Context,
EventEmitter, ForegroundExecutor, Model, ModelContext, Result, Task, TestDispatcher,
TestPlatform, WindowContext,
EventEmitter, ForegroundExecutor, Model, ModelContext, Render, Result, Task, TestDispatcher,
TestPlatform, ViewContext, VisualContext, WindowContext, WindowHandle, WindowOptions,
};
use anyhow::{anyhow, bail};
use futures::{Stream, StreamExt};
@ -12,6 +12,7 @@ pub struct TestAppContext {
pub app: Rc<AppCell>,
pub background_executor: BackgroundExecutor,
pub foreground_executor: ForegroundExecutor,
pub dispatcher: TestDispatcher,
}
impl Context for TestAppContext {
@ -44,13 +45,25 @@ impl Context for TestAppContext {
let mut lock = self.app.borrow_mut();
lock.update_window(window, f)
}
fn read_model<T, R>(
&self,
handle: &Model<T>,
read: impl FnOnce(&T, &AppContext) -> R,
) -> Self::Result<R>
where
T: 'static,
{
let app = self.app.borrow();
app.read_model(handle, read)
}
}
impl TestAppContext {
pub fn new(dispatcher: TestDispatcher) -> Self {
let dispatcher = Arc::new(dispatcher);
let background_executor = BackgroundExecutor::new(dispatcher.clone());
let foreground_executor = ForegroundExecutor::new(dispatcher);
let arc_dispatcher = Arc::new(dispatcher.clone());
let background_executor = BackgroundExecutor::new(arc_dispatcher.clone());
let foreground_executor = ForegroundExecutor::new(arc_dispatcher);
let platform = Rc::new(TestPlatform::new(
background_executor.clone(),
foreground_executor.clone(),
@ -61,9 +74,14 @@ impl TestAppContext {
app: AppContext::new(platform, asset_source, http_client),
background_executor,
foreground_executor,
dispatcher: dispatcher.clone(),
}
}
pub fn new_app(&self) -> TestAppContext {
Self::new(self.dispatcher.clone())
}
pub fn quit(&self) {
self.app.borrow_mut().quit();
}
@ -87,6 +105,20 @@ impl TestAppContext {
cx.update(f)
}
pub fn read<R>(&self, f: impl FnOnce(&AppContext) -> R) -> R {
let cx = self.app.borrow();
f(&*cx)
}
pub fn add_window<F, V>(&mut self, build_window: F) -> WindowHandle<V>
where
F: FnOnce(&mut ViewContext<V>) -> V,
V: Render,
{
let mut cx = self.app.borrow_mut();
cx.open_window(WindowOptions::default(), |cx| cx.build_view(build_window))
}
pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut) -> Task<R>
where
Fut: Future<Output = R> + 'static,

View file

@ -17,6 +17,9 @@ use std::{
use util::TryFutureExt;
use waker_fn::waker_fn;
#[cfg(any(test, feature = "test-support"))]
use rand::rngs::StdRng;
#[derive(Clone)]
pub struct BackgroundExecutor {
dispatcher: Arc<dyn PlatformDispatcher>,
@ -219,6 +222,16 @@ impl BackgroundExecutor {
self.dispatcher.as_test().unwrap().allow_parking();
}
#[cfg(any(test, feature = "test-support"))]
pub fn record_backtrace(&self) {
self.dispatcher.as_test().unwrap().record_backtrace();
}
#[cfg(any(test, feature = "test-support"))]
pub fn rng(&self) -> StdRng {
self.dispatcher.as_test().unwrap().rng()
}
pub fn num_cpus(&self) -> usize {
num_cpus::get()
}

View file

@ -89,6 +89,14 @@ pub trait Context {
where
T: 'static;
fn read_model<T, R>(
&self,
handle: &Model<T>,
read: impl FnOnce(&T, &AppContext) -> R,
) -> Self::Result<R>
where
T: 'static;
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
where
F: FnOnce(AnyView, &mut WindowContext<'_>) -> T;

View file

@ -127,6 +127,14 @@ impl TestDispatcher {
b
})
}
pub fn record_backtrace(&self) {
todo!("record_backtrace")
}
pub fn rng(&self) -> StdRng {
todo!("rng")
}
}
impl Clone for TestDispatcher {

View file

@ -1364,6 +1364,18 @@ impl Context for WindowContext<'_> {
window.update(self.app, update)
}
}
fn read_model<T, R>(
&self,
handle: &Model<T>,
read: impl FnOnce(&T, &AppContext) -> R,
) -> Self::Result<R>
where
T: 'static,
{
let entity = self.entities.read(handle);
read(&*entity, &*self.app)
}
}
impl VisualContext for WindowContext<'_> {
@ -2009,6 +2021,17 @@ impl<V> Context for ViewContext<'_, V> {
{
self.window_cx.update_window(window, update)
}
fn read_model<T, R>(
&self,
handle: &Model<T>,
read: impl FnOnce(&T, &AppContext) -> R,
) -> Self::Result<R>
where
T: 'static,
{
self.window_cx.read_model(handle, read)
}
}
impl<V: 'static> VisualContext for ViewContext<'_, V> {